前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >干货:4个小技巧助你搞定缺失、混乱的数据(附实例代码)

干货:4个小技巧助你搞定缺失、混乱的数据(附实例代码)

作者头像
IT阅读排行榜
发布2019-03-01 16:57:37
1.5K0
发布2019-03-01 16:57:37
举报
文章被收录于专栏:华章科技华章科技

导读:数据工作者经常会遇到各种状况,比如你收集到的数据并不像你期待的那样完整、干净。此前我们讲解了用OpenRefine搞定数据清洗,本文进一步探讨用pandas和NumPy插补缺失数据并将数据规范化、标准化。

作者:托马兹·卓巴斯(Tomasz Drabas)

如需转载请联系大数据(ID:hzdashuju)

本文将使用一个数据集,包含985项真实的房产交易。这些交易是连续5天内在Sacramento发生的。数据下载自:

http://samplecsvs.s3.amazonaws.com/Sacramentorealestatetransactions.csv

数据已转成多种格式,放在GitHub代码库的Data/Chapter01文件夹中。

https://github.com/drabastomek/practicalDataAnalysisCookbook.git

01 插补缺失值

数据的收集工作很棘手。收集工具坏了,调查问卷上某些问题人们不想回答,或者文件被损坏了;这些还只是数据集可能不全的一小部分原因。如果想使用这个数据集,我们有两个选择:忽略缺失的数据,或者用一些值替代。

1. 准备

要实践本技巧,你要先装好pandas模块。

2. 怎么做

csv_read DataFrame可供使用。要插补缺失值,你只需要使用下面的代码(data_imput.py文件):

代码语言:javascript
复制
# 估算平均数以替代空值
csv_read['price_mean'] = csv_read['price'] \
.fillna(
csv_read.groupby('zip')['price'].transform('mean')
)

3. 原理

pandas的.fillna(...)方法帮我们处理了所有重活。这是DataFrame对象的一个方法,将要估算的值作为唯一必须传入的参数。

查阅pandas文档中.fillna(...)的部分,了解可传入的其他参数。文档位于:

http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.fillna.html

在我们的处理过程中,我们假设每个邮编可能会有不同的均价。这就是我们用.groupby(...)方法对数据分组的原因。房产的价格重度依赖于房间的数目,这个推论也是成立的;如果我们的数据集更大,我们还能考虑beds这个变量。

.groupby(...)方法返回一个GroupBy对象。其.transform(...)方法高效地对邮编分组,在我们的例子中,分组的依据是各邮编价格数据的平均数。

现在,.fillna(...)方法简单地用这个平均数替代缺失的观测数据即可。

4. 更多

插补数据不是填补缺失值的唯一方法。数据对称分布且没有异常值时,才会返回一个合理的值;如果分布比较偏,平均值是有偏差的。衡量集中趋势更好的维度是中位数。我们前面的例子只需要改一个小地方:

代码语言:javascript
复制
# 估算中位数以替代空值
csv_read['price_median'] = csv_read['price'] \
.fillna(
csv_read.groupby('zip')['price'].transform('median')
)

02 将特征规范化、标准化

为了提高计算效率,我们将特征规范化(或标准化),这样不会超出计算机的限制。探索模型中变量之间的相互作用时也建议这么处理。

计算机是有限制的:整型值是有上限的(尽管目前在64位机器上这不是个问题),浮点型的精确度也有上限。

数据规范化是让所有的值落在0到1的范围内(闭区间)。数据标准化是移动其分布,使得数据的平均数是0、标准差是1。

1. 准备

要实践本技巧,你要先装好pandas模块。

其他没有什么要准备的了。

2. 怎么做

要实现规范化与标准化,我们定义了两个辅助函数(data_standardize.py文件):

代码语言:javascript
复制
def normalize(col):
'''
规范化
'''
return (col - col.min()) / (col.max() - col.min())
def standardize(col):
'''
标准化
'''
return (col - col.mean()) / col.std()

3. 原理

要规范化数据,即让每个值都落在0和1之间,我们减去数据的最小值,并除以样本的范围。统计学上的范围指的是最大值与最小值的差。normalize(...)方法就是做的前面描述的工作:对数据的集合,减去最小值,除以范围。

标准化的过程类似:减去平均数,除以样本的标准差。这样,处理后的数据,平均数为0而标准差为1。standardize(...)方法做了这些处理:

代码语言:javascript
复制
csv_read['n_price_mean'] = normalize(csv_read['price_mean'])
csv_read['s_price_mean'] = standardize(csv_read['price_mean'])

03 分级数据

当我们想查看数据分布的形状,或将数据转换为有序的形式时,数据分级就派上用场了。

1. 准备

要实践本技巧,你要先装好pandas和NumPy模块。

2. 怎么做

可以用下面的代码(data_binning.py文件)对数据分级(比如处理成直方图):

代码语言:javascript
复制
# 根据线性划分的价格的范围,创建价格的容器
bins = np.linspace(
csv_read['price_mean'].min(),
csv_read['price_mean'].max(),
6
)
# 将容器应用到数据上
csv_read['b_price'] = np.digitize(
csv_read['price_mean'],
bins
)

3. 原理

第一步是创建容器。对于价格数据(缺失值用估算的平均数填补),我们创建了六个容器,在最小值和最大值之间均匀分配。.linspace(...)方法做了这点工作:创建长度为6的NumPy数组,其中每个元素比前一个大固定的差值。比如,.linspace(0, 6, 6)生成数组[0., 1.2, 2.4, 3.6, 4.8, 6.]。

NumPy对线性代数来说是个强大的数字处理库。可轻松处理大型数组和矩阵,还提供了极其丰富的函数操作数据。想了解更多,可访问:

http://www.numpy.org

.digitize(...)方法对指定列中的每个值,都返回所属的容器索引。第一个参数是要分级的列,第二个参数是容器的数组。

使用DataFrame的.value_counts()得到每个容器中的记录计数,counts_b = csv_read['b_price'].value_counts()。

4. 更多

有时候我们不会用均匀间隔的值,我们会让每个桶中拥有相同的数目。要达成这个目标,我们可以使用分位数。

分位数与百分位数有紧密的联系。区别在于百分位数返回的是给定百分数的值,而分位数返回的是给定分位点的值。想了解更多,可访问:

https://www.stat.auckland.ac.nz/~ihaka/787/lectures-quantiles-handouts.pdf

我们想把列拆成十分位数,即10个(差不多)相等的容器。要做到这点,我们可以使用下面的代码(你可以一眼看出其和之前方法的相似之处):

代码语言:javascript
复制
# 根据十分位数创建容器
decile = csv_read['price_mean'].quantile(np.linspace(0, 1, 11))
# 将容器应用到数据上
csv_read['p_price'] = np.digitize(
csv_read['price_mean'],
decile
)

.quantile(...)方法可以传一个(0到1之间的)数字,来表明要返回的分位数(例如,0.5是中位数,0.25和0.75是上下四分位数)。它也可以传入一个分位的列表,返回相应的值的数组。.linspace(0, 1, 11)方法会生成这个数组:

代码语言:javascript
复制
[ 0., 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.]

所以,.quantile(...)方法会以price_mean列的最小值开始,直到最大值,返回十分位数的列表。

04 编码分类变量

为数据的探索阶段准备的最后一步就是分类变量了。有些软件包在背后做了这个工作,但最好还是理解这步处理的时机与做法。

统计模型只能接受有序的数据。分类变量(有时根据上下文可表示为数字)不能直接在模型中使用。要使用它们,我们要先进行编码,也就是给它们一个唯一的数字编号。这解释了什么时候做。至于如何做—应用下述技巧即可。

1. 准备

要实践本技巧,你要先装好pandas模块。

其他没有什么要准备的了。

2. 怎么做

pandas又提供了一个方法,帮我们做完所有事(data_dummy_code.py文件):

代码语言:javascript
复制
# 根据房产类型处理的简单代码
csv_read = pd.get_dummies(
csv_read,
prefix='d',
columns=['type']
)

3. 原理

.get_dummies(...)方法将分类变量转换为简单的变量。比如,考虑一个变量,以三种水平中的某一种作为值:

代码语言:javascript
复制
1 One
2 Two
3 Three

需要用三列进行编码:

代码语言:javascript
复制
1 One 1 0 0
2 Two 0 1 0
3 Three 0 0 1

有时可用两列。如果有一个水平等效于null的话,我们可以这样做:

代码语言:javascript
复制
1 One 1 0 
2 Two 0 1 
3 Three 0 0 

.get_dummies(...)方法的第一个参数是DataFrame对象。columns参数指定了代码要处理的DataFrame的列(或某些列,因为可以传入列表)。通过指定前缀,我们告诉方法生成的列名以d打头;本例中生成的列会叫d_Condo。下划线是默认的,可以通过指定prefix_sep参数更改。

.get_dummies(...)方法的完整参数列表,参见:

http://pandas.pydata.org/pandas-docs/stable/generated/pandas.get_dummies.html

关于作者:托马兹·卓巴斯(Tomasz Drabas),微软数据科学家,致力于解决高维特征空间的问题。他有超过13年的数据分析和数据科学经验:在欧洲、澳大利亚和北美洲三大洲期间,工作领域遍及高新技术、航空、电信、金融和咨询。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-01-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 大数据DT 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档