# 缺失值的处理 面对大量数据经常会出现残缺不全的情况,面对这样的数据我们需要对缺失值进行预先处理。 填充缺失值一般用两个值: - None: 对象类型内容的默认缺失值 - NaN: 数值类型的默认缺失值,用numpy.nan表示 需要注意的是: - 不同语言/工具可能对缺失值的默认处理方式不同,所以,如果拿到的是别的处理过的文件,可能需要对已经替换过的缺失值再进行替换一次。 - NaN的使用具有传染性,就是任何数据跟NaN进行操作,最终的结果都是NaN, 性质很像乘法中的0,所以在有的操作函数中,numpy提供了另外一套操作,对NaN缺失值自动过滤掉,而不是让他传染给所有结果 - None和NaN可以互换,或者可以认为这两个值在Pandas中等价 ## 对NaN不敏感的操作函数 有时候NaN的传染性并不是让人喜欢,他会导致我们的结果出现重大偏差甚至错误,所以在处理的时候我们还提供了另外一套对NaN不敏感的函数: - np.nansum - np.nanmin - np.nanmax ```python # 创建带有NaN的数组 a = np.array([3, 2, 3, np.nan, 4]) print("a = \n", a) print() # 对于普通的函数操作,NaN具有传染性 print("np.sum = ", np.sum(a)) print("np.min = ", np.min(a)) print("np.max = ", np.max(a))b' # 如果想避免NaN传染性带来的问题,需要使用相应NaN非敏感函数 print("np.nansum = ", np.nansum(a)) print("np.nanmin = ", np.nanmin(a)) print("np.nanmax = ", np.nanmax(a)) ``` a = [ 3. 2. 3. nan 4.] np.sum = nan np.min = nan np.max = nan np.nansum = 12.0 np.nanmin = 2.0 np.nanmax = 4.0 /Users/augs/anaconda3/lib/python3.7/site-packages/numpy/core/fromnumeric.py:83: RuntimeWarning: invalid value encountered in reduce return ufunc.reduce(obj, axis, dtype, out, **passkwargs) ## 缺失值的发现 发现缺失值可以使用两个函数: - isnull - notnull 每个函数都返回布尔类型的掩码数据。 ```python # 准备的实验数据 data = pd.Series([23, np.nan, "hahaha", "two", 23, None]) print("data = \n ", data) ``` data = 0 23 1 NaN 2 hahaha 3 two 4 23 5 None dtype: object ```python # isnull用来判断是否是空 # isnull返回的是布尔值 print("\n data.isnull = \n", data.isnull()) # notnull返回的是布尔值 print("\n data.notnull = \n", data.notnull()) # 可以使用这个作为掩码操作 print("\n data[data.notnull()] = \n", data[data.notnull()]) ``` data.isnull = 0 False 1 True 2 False 3 False 4 False 5 True dtype: bool data.notnull = 0 True 1 False 2 True 3 True 4 True 5 False dtype: bool data[data.notnull()] = 0 23 2 hahaha 3 two 4 23 dtype: object ## 剔除缺失值 对于缺失值的处理一般是剔除或者用一个特殊的值来进行填充: - dropna: 剔除缺失值,常用的两个参数: - axis: 控制剔除行或者列 - thresh:如果有效数据数量低于这个值,则对应的行或列将被剔除 - fillna: 缺失值用别的值进行填充 ```python # 剔除缺失值 # 剔除后只留下原来的真正的值 print("\n data.dropna = \n", data.dropna()) ``` data.dropna = 0 23 2 hahaha 3 two 4 23 dtype: object ```python # 需要注意的是,如果是二维数据,剔除后需要把整行都剔除,不仅仅是把NaN的一个值剔除 df = pd.DataFrame([[1, np.nan, 3], [2, 4, 9], [np.nan, np.nan, 9]]) print("\n df.dropna = \n", df.dropna()) ``` df.dropna = 0 1 2 1 2.0 4.0 9 ```python # 如果改变剔除的默认行为,比如剔除包含NaN的行,则需要axis参数 print("\n df.dropna(axis='columns') = \n", df.dropna(axis='columns')) ``` df.dropna(axis='columns') = 2 0 3 1 9 2 9 ```python # thresh参数 # 数据列中,低于thresh=2的列被剔除 print("\n df.dropna(axis='columns') = \n", df.dropna(axis='columns', thresh=2)) ``` df.dropna(axis='columns') = 0 2 0 1.0 3 1 2.0 9 2 NaN 9 ## 填充缺失值 对于缺失值一般使用换一个特定的值进行填充就可以。填充的时候可以使用一些特定的值,比如0,-1等,也可以使用一些处理后的值,比如填充(imputation)或者转换(interpolation)之后的数据。 填充函数是fillna,常用参数为: - axis: 坐标轴,行或者列 - method: 填充方式 - ffill: forward-fill, 从前向后填充 - bfill: backward-fill, 从后向前填充 ```python # 准备数据 df = pd.DataFrame([[1, np.nan, 3], [2, 4, 9], [np.nan, np.nan, 9]]) print("\n df = \n", df) ``` df = 0 1 2 0 1.0 NaN 3 1 2.0 4.0 9 2 NaN NaN 9 ```python # 使用某一个值进行填充 print("df.fillna = \n", df.fillna(-1)) ``` df.fillna = 0 1 2 0 1.0 -1.0 3 1 2.0 4.0 9 2 -1.0 -1.0 9 ```python # forward-fill print("df.fillna(ffill) = \n", df.fillna( method="ffill")) ``` df.fillna(ffill) = 0 1 2 0 1.0 NaN 3 1 2.0 4.0 9 2 2.0 4.0 9 ```python # backward-fill print("df.fillna(bfill) = \n", df.fillna(axis=1, method="bfill")) ``` df.fillna(bfill) = 0 1 2 0 1.0 3.0 3.0 1 2.0 4.0 9.0 2 9.0 9.0 9.0