我爱编程

【Chapter 7.1 】处理缺失数据

2018-05-25  本文已影响0人  蜘蛛的梦呓

【Chapter 7】 数据清洗和准备

其实数据分析中80%的时间都是在数据清理部分,loading, clearning, transforming, rearranging。而pandas非常适合用来执行这些任务。

7.1 处理缺失数据

在许多数据分析工作中,缺失数据是经常发生的。pandas的目标之一就是尽量轻松地处理缺失数据。例如,pandas对象的所有描述性统计默认都不包括缺失数据。

缺失数据在pandas中呈现的方式有些不完美,但对于大多数用户可以保证功能正常。对于数值数据,pandas使用浮点值NaN(Not a Number)表示缺失数据。我们称其为哨兵值,可以方便的检测出来:

string_data = pd.Series(['aardvark', 'artichoke', np.nan, 'avocado'])

string_data
Out[417]: 
0     aardvark
1    artichoke
2          NaN
3      avocado
dtype: object

string_data.isnull()
Out[418]: 
0    False
1    False
2     True
3    False
dtype: bool

在pandas中,我们采用了R语言中的惯用法,即将缺失值表示为NA,它表示不可用not available。在统计应用中,NA数据可能是不存在的数据或者虽然存在,但是没有观察到(例如,数据采集中发生了问题)。当进行数据清洗以进行分析时,最好直接对缺失数据进行分析,以判断数据采集的问题或缺失数据可能导致的偏差。

Python内置的None值在对象数组中也可以作为NA:

string_data[0] = None

string_data.isnull()
Out[420]: 
0     True
1    False
2     True
3    False
dtype: bool

pandas项目中还在不断优化内部细节以更好处理缺失数据,像用户API功能,例如pandas.isnull,去除了许多恼人的细节。表7-1列出了一些关于缺失数据处理的函数。

1 Filtering Out Missing Data(过滤缺失值)

有一些方法来过滤缺失值。可以使用pandas.isnull和boolean indexing, 配合使用dropna。对于series,只会返回non-null数据和index values:

from numpy import nan as NA

data = pd.Series([1, NA, 3.5, NA, 7])

data.dropna()
Out[423]: 
0    1.0
2    3.5
4    7.0
dtype: float64

上面的等同于:

data[data.notnull()]
Out[424]: 
0    1.0
2    3.5
4    7.0
dtype: float64

对于DataFrame,会复杂一些。你可能想要删除包含有NA的row和column。dropna默认会删除包含有缺失值的row:

data = pd.DataFrame([[1., 6.5, 3.], [1., NA, NA],
                     [NA, NA, NA], [NA, 6.5, 3.]])
data
                     
Out[426]: 
     0    1    2
0  1.0  6.5  3.0
1  1.0  NaN  NaN
2  NaN  NaN  NaN
3  NaN  6.5  3.0
cleaned = data.dropna()#dropna默认会删除包含有缺失值的row
cleaned
Out[428]: 
     0    1    2
0  1.0  6.5  3.0

设定how=all只会删除那些全是NA的行:

data.dropna(how='all')#设定how=all只会删除那些全是NA的行:
Out[429]: 
     0    1    2
0  1.0  6.5  3.0
1  1.0  NaN  NaN
3  NaN  6.5  3.0

删除列也一样,设置axis=1:

data[4] = NA
data

Out[430]: 
     0    1    2   4
0  1.0  6.5  3.0 NaN
1  1.0  NaN  NaN NaN
2  NaN  NaN  NaN NaN
3  NaN  6.5  3.0 NaN
data.dropna(axis=1, how='all')
Out[431]: 
     0    1    2
0  1.0  6.5  3.0
1  1.0  NaN  NaN
2  NaN  NaN  NaN
3  NaN  6.5  3.0

一种删除DataFrame row的相关应用是是time series data。假设你想要保留有特定数字的观测结果,可以使用thresh参数:

df = pd.DataFrame(np.random.randn(7, 3))

df
Out[433]: 
          0         1         2
0  0.699758 -1.364918 -0.158327
1  0.479697 -1.088628 -0.513005
2  0.040280  0.267692 -0.740376
3  0.429005  0.767700  0.200298
4  0.440503  1.318111 -0.441456
5 -0.727582 -1.780834 -1.030871
6  0.979551 -0.339133 -0.504945
df.iloc[:4, 1] = NA
dfdf.iloc[:4, 1] = NA
df

    0           1   2
0   -0.986575   NaN -0.251823
1   2.008704    NaN 1.827761
2   2.240856    NaN 0.273062
3   0.777182    NaN -0.220044
4   0.327522    0.781662    -0.651949
5   1.454611    -0.170581   -1.740959
6   -0.711897   0.074983    1.343807
df.iloc[:2, 2] = NA
df

Out[435]: 
          0         1         2
0  0.699758       NaN       NaN
1  0.479697       NaN       NaN
2  0.040280       NaN -0.740376
3  0.429005       NaN  0.200298
4  0.440503  1.318111 -0.441456
5 -0.727582 -1.780834 -1.030871
6  0.979551 -0.339133 -0.504945
df.dropna()
Out[436]: 
          0         1         2
4  0.440503  1.318111 -0.441456
5 -0.727582 -1.780834 -1.030871
6  0.979551 -0.339133 -0.504945
df.dropna(thresh=2)#删除缺失2个值以上的行 
Out[437]: 
          0         1         2
2  0.040280       NaN -0.740376
3  0.429005       NaN  0.200298
4  0.440503  1.318111 -0.441456
5 -0.727582 -1.780834 -1.030871
6  0.979551 -0.339133 -0.504945

2 Filling In Missing Data(填补缺失值)

不是删除缺失值,而是用一些数字填补。对于大部分目的,fillna是可以用的。调用fillna的时候设置好一个常用用来替换缺失值:

df.fillna(0)
Out[438]: 
          0         1         2
0  0.699758  0.000000  0.000000
1  0.479697  0.000000  0.000000
2  0.040280  0.000000 -0.740376
3  0.429005  0.000000  0.200298
4  0.440503  1.318111 -0.441456
5 -0.727582 -1.780834 -1.030871
6  0.979551 -0.339133 -0.504945

给fillna传入一个dict,可以给不同列替换不同的值:


df.fillna({1: 0.5, 2: 0})
Out[439]: 
          0         1         2
0  0.699758  0.500000  0.000000
1  0.479697  0.500000  0.000000
2  0.040280  0.500000 -0.740376
3  0.429005  0.500000  0.200298
4  0.440503  1.318111 -0.441456
5 -0.727582 -1.780834 -1.030871
6  0.979551 -0.339133 -0.504945

fillna返回一个新对象,但你可以使用in-place来直接更改原有的数据:

_ = df.fillna(0, inplace=True)
df

Out[440]: 
          0         1         2
0  0.699758  0.000000  0.000000
1  0.479697  0.000000  0.000000
2  0.040280  0.000000 -0.740376
3  0.429005  0.000000  0.200298
4  0.440503  1.318111 -0.441456
5 -0.727582 -1.780834 -1.030871
6  0.979551 -0.339133 -0.504945

在使用fillna的时候,这种插入法同样能用于reindexing:

df = pd.DataFrame(np.random.randn(6, 3))
df

Out[441]: 
          0         1         2
0 -0.191850 -1.956573 -1.217991
1  1.103721 -0.326794 -0.518728
2  1.351338 -0.580486  1.993749
3 -1.124328  0.164845  0.000960
4  1.715065  0.416267  0.795450
5  0.162924 -0.831497 -0.164063
df.iloc[2:, 1] = NA
df

Out[442]: 
          0         1         2
0 -0.191850 -1.956573 -1.217991
1  1.103721 -0.326794 -0.518728
2  1.351338       NaN  1.993749
3 -1.124328       NaN  0.000960
4  1.715065       NaN  0.795450
5  0.162924       NaN -0.164063
df.fillna(method='ffill') #根据最后一位有效值,自动补全
Out[443]: 
          0         1         2
0 -0.191850 -1.956573 -1.217991
1  1.103721 -0.326794 -0.518728
2  1.351338 -0.326794  1.993749
3 -1.124328 -0.326794  0.000960
4  1.715065 -0.326794  0.795450
5  0.162924 -0.326794 -0.164063

limit : int, 默认值 None; 如果指定了方法,则这是连续的NaN值的前向/后向填充的最大数量。 换句话说,如果连续NaN数量超过这个数字,它将只被部分填充。 如果未指定方法,则这是沿着整个轴的最大数量,其中NaN将被填充。 如果不是无,则必须大于0。

df.fillna(method='ffill', limit=2) 
Out[444]: 
          0         1         2
0 -0.191850 -1.956573 -1.217991
1  1.103721 -0.326794 -0.518728
2  1.351338 -0.326794  1.993749
3 -1.124328 -0.326794  0.000960
4  1.715065       NaN  0.795450
5  0.162924       NaN -0.164063

只要有些创新,你就可以利用fillna实现许多别的功能。比如说,你可以传入Series的平均值或中位数:

In [43]: data = pd.Series([1., NA, 3.5, NA, 7])

In [44]: data.fillna(data.mean())#平均值
Out[44]: 
0    1.000000
1    3.833333
2    3.500000
3    3.833333
4    7.000000
dtype: float64

表7-2列出了fillna的参考。

img img
上一篇 下一篇

猜你喜欢

热点阅读