文中所用数据集已上传,找不到的可以私聊我
学习目标
知道空值和缺失值的区别以及缺失值的影响
知道如何查看数据集缺失值情况的方法
知道缺失值处理的办法
1 NaN简介
好多数据集都含缺失数据。缺失数据有多种表现形式
数据库中,缺失数据表示为
NULL
在某些编程语言中用
NA
或None
表示缺失值也可能是空字符串
''
或数值0
在Pandas中使用
NaN
表示缺失值
Pandas中的NaN值来自NumPy库,NumPy中缺失值有几种表示形式:NaN,NAN,nan,他们都一样
-
缺失值和其它类型的数据不同,它毫无意义,NaN不等于0,也不等于空字符串
from numpy import NaN,NAN,nan print(NaN==True) print(NaN==False) print(NaN==0) print(NaN=='') print(NaN==None) # 输出结果如下 False False False False False
-
两个NaN也不相等
print(NaN==NaN) print(NaN==nan) print(NaN==NAN) print(nan==NAN) # 输出结果如下 False False False False
-
缺失值从何而来呢?缺失值的来源有两个:
-
原始数据包含缺失值
-
数据整理过程中产生缺失值
-
2 加载包含缺失的数据
加载数据时可以通过
keep_default_na
与na_values
指定加载数据时的缺失值
-
df = pd.read_csv('../data/city_day.csv') print(df.head()) # 输出结果如下City Date PM2.5 PM10 ... Toluene Xylene AQI AQI_Bucket 0 Ahmedabad 2015-01-01 NaN NaN ... 0.02 0.00 NaN NaN 1 Ahmedabad 2015-01-02 NaN NaN ... 5.50 3.77 NaN NaN 2 Ahmedabad 2015-01-03 NaN NaN ... 16.40 2.25 NaN NaN 3 Ahmedabad 2015-01-04 NaN NaN ... 10.14 1.00 NaN NaN 4 Ahmedabad 2015-01-05 NaN NaN ... 18.89 2.78 NaN NaN [5 rows x 16 columns]
加载数据,观察缺失值默认的显示情况
df = pd.read_csv('../data/city_day.csv') print(df.head()) # 输出结果如下City Date PM2.5 PM10 ... Toluene Xylene AQI AQI_Bucket 0 Ahmedabad 2015-01-01 NaN NaN ... 0.02 0.00 NaN NaN 1 Ahmedabad 2015-01-02 NaN NaN ... 5.50 3.77 NaN NaN 2 Ahmedabad 2015-01-03 NaN NaN ... 16.40 2.25 NaN NaN 3 Ahmedabad 2015-01-04 NaN NaN ... 10.14 1.00 NaN NaN 4 Ahmedabad 2015-01-05 NaN NaN ... 18.89 2.78 NaN NaN [5 rows x 16 columns]
-
使用
keep_default_na=False
参数加载数据,不显示默认缺失值df = pd.read_csv('../data/city_day.csv', keep_default_na=False) print(df.head()) # 输出结果如下City Date PM2.5 PM10 NO ... Benzene Toluene Xylene AQI AQI_Bucket 0 Ahmedabad 2015-01-01 0.92 ... 0.0 0.02 0.0 1 Ahmedabad 2015-01-02 0.97 ... 3.68 5.5 3.77 2 Ahmedabad 2015-01-03 17.4 ... 6.8 16.4 2.25 3 Ahmedabad 2015-01-04 1.7 ... 4.43 10.14 1.0 4 Ahmedabad 2015-01-05 22.1 ... 7.01 18.89 2.78 [5 rows x 16 columns]
-
使用
na_values
参数加载数据,通过该参数指定我们认为的缺失值# 在这里我们通过na_values参数,指鹿为马 # 比如我们认为你的值是Ahmedabad,则也是缺失,这些值会被替换成NaN df = pd.read_csv('../data/city_day.csv', na_values=["Ahmedabad"], keep_default_na=True) print(df.head()) # 输出结果如下City Date PM2.5 PM10 NO ... Benzene Toluene Xylene AQI AQI_Bucket 0 NaN 2015-01-01 0.92 ... 0.0 0.02 0.0 1 NaN 2015-01-02 0.97 ... 3.68 5.5 3.77 2 NaN 2015-01-03 17.4 ... 6.8 16.4 2.25 3 NaN 2015-01-04 1.7 ... 4.43 10.14 1.0 4 NaN 2015-01-05 22.1 ... 7.01 18.89 2.78 [5 rows x 16 columns]
3 查看缺失值
3.1 加载数据并通过info函数初步查看缺失值情况
-
加载印度城市空气质量数据集,并初步查探缺失值
df = pd.read_csv('../data/city_day.csv') df.info() # 输出结果如下 <class 'pandas.core.frame.DataFrame'> RangeIndex: 29531 entries, 0 to 29530 # 总的行数是:29531 Data columns (total 16 columns):# Column Non-Null Count Dtype --- ------ -------------- ----- 0 City 29531 non-null object # 非空的行数是29531行,也就是一行也不空1 Date 29531 non-null object 2 PM2.5 24933 non-null float643 PM10 18391 non-null float644 NO 25949 non-null float645 NO2 25946 non-null float646 NOx 25346 non-null float647 NH3 19203 non-null float648 CO 27472 non-null float649 SO2 25677 non-null float6410 O3 25509 non-null float6411 Benzene 23908 non-null float6412 Toluene 21490 non-null float6413 Xylene 11422 non-null float64 # 非空的行数是11422行,也就是有一多半都是空值14 AQI 24850 non-null float6415 AQI_Bucket 24850 non-null object dtypes: float64(13), object(3) memory usage: 3.6+ MB
3.2 isnull函数和notnull函数判断是否存在缺失值
-
pd.isnull
与pd.isna
用法相同# 判断是否为缺失值 # 如果值是缺失值返回True,否则返回False print(df.head().isnull()) print(df['PM2.5'].head().isna())
notnull函数和notna函数相同,判断是否存在非缺失值;与isnull函数对应,返回结果正好相反# 判
断是否为非缺失值 # 缺失值返回False print(df.head().notnull()) print(df['PM2.5'].head().notna()) # 输出结果如下City Date PM2.5 PM10 NO ... Benzene Toluene Xylene AQI AQI_Bucket 0 True True False False True ... True True True False False 1 True True False False True ... True True True False False 2 True True False False True ... True True True False False 3 True True False False True ... True True True False False 4 True True False False True ... True True True False False [5 rows x 16 columns] 0 False 1 False 2 False 3 False 4 False Name: PM2.5, dtype: bool
3.3 df.isnull().sum()空值数量统计
# 缺失值数量统计
print(df.isnull().sum())
print(df['PM2.5'].isnull().sum())
# 非缺失值数量统计
print(df.notnull().sum())
print(df['PM2.5'].notnull().sum())
# 输出结果如下
City 0
Date 0
PM2.5 4598
PM10 11140
NO 3582
NO2 3585
NOx 4185
NH3 10328
CO 2059
SO2 3854
O3 4022
Benzene 5623
Toluene 8041
Xylene 18109
AQI 4681
AQI_Bucket 4681
dtype: int64
4598
City 29531
Date 29531
PM2.5 24933
PM10 18391
NO 25949
NO2 25946
NOx 25346
NH3 19203
CO 27472
SO2 25677
O3 25509
Benzene 23908
Toluene 21490
Xylene 11422
AQI 24850
AQI_Bucket 24850
dtype: int64
24933
3.4 Missingno库对缺失值的情况进行可视化探查
可以使用第三方库Missingno来对缺失值进行可视化
3.4.1 安装missingno库
-
通过pip安装missingno
pip install missingno -i https://pypi.tuna.tsinghua.edu.cn/simple/
3.4.2 missingno.bar(df)缺失值数量可视化
-
导包并利用
missingno.bar(df)
函数查看数据集数据完整性import pandas as pd import missingno as msno import matplotlib.pyplot as plt # 加载数据集 df = pd.read_csv('../data/city_day.csv') # 查看非缺失值数量 print(df.notna().sum()) # 可视化查看缺失值数量情况 msno.bar(df) # 查看图表# 在有些平台,不加该语句,以上的图表不能显示,如果上边的msno.bar(df)可以显示图表,也可以不加该语句 plt.show()
3.4.3 missingno.matrix(df)缺失值位置的可视化
-
missingno.matrix(df)` 可以快速直观的查看缺失值的分布情况
print(msno.matrix(df)) # 对数据集进行随机取样后再查看数据缺失情况 print(msno.matrix(df.sample(100))) plt.show()
-
有缺失值的地方,图都显示为空白。 例如,在
City
列中没有白线,说明该列无缺失值。 -
右侧的迷你图给出了数据完整性的情况,表示每行数据非空值的多少,其中的数字1表示该行数据只有1列为非空,数字15表示该行数据有15列为非空数据,显示的1和15为整个数据集所有数据行中非空值的最小值和最大值
2.4.4 missingno.heatmap(df)缺失值之间相关性可视化
print(msno.heatmap(df))
plt.show()
-
相关性取值 0 不相关,1强相关,-1强负相关
4 缺失值处理
缺失值的处理方法有以下几种方式:
删除缺失值:删除缺失值会损失信息,并不推荐删除,当缺失数据占比较高的时候,或可以忽略相关性时,可以尝试使用删除缺失值
填充缺失值:填充缺失值是指用一个估算的值来去替代缺失数
平均值、中位数
前后值填充,数据呈现顺序变化的时候可以使用缺失值前边或后边的值进行填充
线性插值:假定数据点之间存在严格的线性关系,并利用相邻数据点中的非缺失值来计算缺失数据点的值
4.1 dropna删除缺失值
-
使用
dropna
函数来删除空值,具体用法如下# 函数用法 df.dropna( axis=0, how='any', inplace=True, subset=['列名',...], thresh=10 ) df.drop() # 按列删除
-
dropna
函数参数解释-
axis=0
-
可选参数 ,默认为0按行删
-
0, or 'index':删除包含缺失值的行
-
1, or 'columns':删除包含缺失值的列
-
-
how='any'
-
可选参数,默认为any
-
any: 如果存在NA值,则删除该行或列
-
all: 如果所有值都是NA,则删除该行或列
-
-
inplace=False
-
可选参数,不建议使用这个参数
-
默认False, 不对原数据集进行修改
-
inplce=True,对原数据集进行修改
-
-
subset接收一个列表
-
接收一个列表,列表中的元素为列名: 对特定的列
df = pd.read_csv('../data/city_day.csv') # 随机获取10条数据 df2 = df.sample(n=10, random_state=5) print(df2) # 删除含有缺失值的行数据 print(df2.dropna()) # 删除含有缺失值的列 print(df2.dropna(axis=1)) # 删除指定列中含有缺失值的行数据 print(df2.dropna(how='any', subset=['PM2.5', 'Xylene', 'AQI'])) # 删除指定列中都含有缺失值的行数据 print(df2.dropna(how='all', subset=['PM2.5', 'Xylene', 'AQI'])) # 删除含有缺失值的行数据, 剩余非空值个数大于等于12的行数据保留 print(df2.dropna(thresh=12))
进行缺失值删除处理
-
-
thresh=n
-
可选参数
-
参数值为int类型,按行去除NaN值,去除NaN值后该行剩余数值的数量(列数)大于等于n,便保留这一行
-
df = pd.read_csv('../data/city_day.csv') # 随机获取10条数据 df2 = df.sample(n=10, random_state=5) print(df2) # 删除含有缺失值的行数据 print(df2.dropna()) # 删除含有缺失值的列 print(df2.dropna(axis=1)) # 删除指定列中含有缺失值的行数据 print(df2.dropna(how='any', subset=['PM2.5', 'Xylene', 'AQI'])) # 删除指定列中都含有缺失值的行数据 print(df2.dropna(how='all', subset=['PM2.5', 'Xylene', 'AQI'])) # 删除含有缺失值的行数据, 剩余非空值个数大于等于12的行数据保留 print(df2.dropna(thresh=12))
-
4.2 fillna固定值填充缺失值
-
用平均值填充PM2.5的缺失值
df = pd.read_csv('../data/city_day.csv') df2 = df.copy() # 计算PM2.5平均值 pm25_mean = df2['PM2.5'].mean() print(pm25_mean) # fillna函数填充缺失值,将返回值赋值给原来的列 df2['PM2.5'] = df2['PM2.5'].fillna(value=pm25_mean) print(df2['PM2.5'].isnull().sum()) # 数据结果如下 67.45057794890272 0
4.3 fillna前后值填充缺失值
时序数据在某一列值的变化往往有一定线性规律,绝大多数的时序数据,具体的列值随着时间的变化而变化,所以对于有时序的行数据缺失值处理可以使用上一个非空值或下一个非空值填充
印度城市空气质量数据明显就是一个时序数据集,空气中的各种成分会随着时间变化而变化,不会出现特别大的急剧变化
-
使用上一个非空值(参数method='ffill')填充
Xylene(二甲苯)
的空值df = pd.read_csv('../data/city_day.csv') s1 = df['Xylene'][54:64] print(s1) # 用上一个非空值填充并赋值指定列 print(s1.fillna(method='ffill')) # 输出结果如下 54 6.05 55 0.81 56 NaN 57 NaN 58 NaN 59 1.32 60 0.22 61 2.25 62 1.55 63 4.13 Name: Xylene, dtype: float64 54 6.05 55 0.81 56 0.81 57 0.81 58 0.81 59 1.32 60 0.22 61 2.25 62 1.55 63 4.13 Name: Xylene, dtype: float64
-
使用下一个非空值(参数method='bfill')填充整个数据集的空值
# 用上一个非空值填充并赋值指定列 print(s1.fillna(method='bfill')) # 输出结果如下 54 6.05 55 0.81 56 1.32 57 1.32 58 1.32 59 1.32 60 0.22 61 2.25 62 1.55 63 4.13 Name: Xylene, dtype: float64
4.4 interpolate线性插值
绝大多数的时序数据,具体的列值随着时间的变化而变化。 因此,除了使用bfill和ffill进行插补以外还可以使用线性插值法:它假定数据点之间存在严格的线性关系,并利用相邻数据点中的非缺失值来计算缺失数据点的值。
-
使用
df.interpolate(limit_direction="both")
对缺失数据进行线性填充p
rint(s1.interpolate()) # 输出结果如下 54 6.0500 55 0.8100 56 0.9375 57 1.0650 58 1.1925 59 1.3200 60 0.2200 61 2.2500 62 1.5500 63 4.1300 Name: Xylene, dtype: float64
总结
缺失值会影响分析计算的结果,这个结果又要用来指导生产经营,所以要重视缺失值
空值仅指Pandas中的空值类型,比如
NaN
缺失值包含空值,也有可能是空字符串、数字0、False或None等
不是空值的缺失值可以通过
replace
函数先替换为NaN
空值,之后再按空值进行处理理解上面的内容,并请对下面的API 有印象、能找到、能理解、能看懂
-
查看空值
-
df.info()
可以查看数据集每一列非空值的数量 -
isnull
¬null
函数 判断是否存在空值 -
df.isnull().sum()
统计空值数量 -
missingno
库可以对空值进行可视化探查-
missingno.matrix(df)
查看缺失值的位置 -
missingno.heatmap(df)
查看缺失值之间的相关性
-
-
-
缺失值的处理
-
df.dropna()
删除缺失值 -
df.fillna(具体值)
将缺失值填充为具体指 -
df.fillna(method='ffill')
使用上一个非空值进行填充 -
df.fillna(method='bfill')
使用下一个非空值进行填充 -
df.interpolate()
线性插值:假定数据点之间存在严格的线性关系,并利用相邻数据点中的非缺失值来计算缺失数据点的值
-