参考资料:活用pandas库
缺失数据有多种表示形式。在数据库中,缺失数据表示为NULL;在某些变成语言中使用NA表示。根据数据的来源,缺失值可能是空字符串("")或数据(比如88或99)。在pandas中使用NaN表示缺失值。
1、何为NaN值
pandas中的NaN值来自numpy库。在numpy中,缺失值有集中表示形式:NaN、NAN或nan,但它们都是等同的。
缺失值和其他类型的数据不同,实际上他们无甚意义。数据缺失了,也就无所谓等于或不等于。NaN也不等同于0或者空字符串。当然一个缺失值和另一个缺失值也是不相等的,pandas提供了isnull和notnull方法,用于判断某个值是否为缺失值。
# 从numpy库导入缺失值
from numpy import NaN,NAN,nan
print(NaN==True)
print('-'*20)
print(NaN==False)
print('-'*20)
print(NaN==0)
print('-'*20)
print(NaN==1)
# 检测缺失值和缺失值是否相等
print(NaN==NaN)
print('-'*20)
print(NaN==nan)
print('-'*20)
print(NaN==NAN)
print('-'*20)
print(nan==NAN)
# isnull方法和notnull方法应用
import pandas as pd
print(pd.isnull(NAN))
print('-'*20)
print(pd.isnull(NaN))
print('-'*20)
print(pd.isnull(nan))
print('-'*20)
print(pd.notnull(NaN))
print('-'*20)
print(pd.notnull(42))
print('-'*20)
print(pd.notnull('string'))
2、缺失值的来源
缺失值的两个来源:一是缺失值的数据集,二是数据整理过程。
(1)加载数据
加载数据时,pandas会自动查找缺失数据单元,并在DataFrame中对该单元给出一个NaN值。在read_csv函数中,有3个参数与缺失值的读取有关:na_values、keep_default_na和na_filter。
na_values参数允许指定额外的缺失值或NaN值。通常采用默认即可,但有些数据集可能会把99指定为缺失值,此时需要设置na_values=[99]来指定缺失值。
keep_default_na参数是布尔值,它允许指定是否要把其他任何值视为缺失值。通常采用默认值True,即使用na_values参数额外指定的缺失值都会追加到缺失值列表中。若把keep_default_na设置为False,将只使用na_values中指定的缺失值。
na_filter参数也是布尔型,用于指定某些值是否会被解读成“缺失值”。默认为True,即缺失值会被编码为NaN。如果设置为False,则不会将任何事重新编码为“缺失值”。
# 指定文件路径
visited_file=r"...\data\survey_visited.csv"
# 使用默认值加载数据
pd.read_csv(visited_file)
(2)合并数据
当进行数据合并的时候,有时因两个表中的内容差异,而产生缺失值。
visited=pd.read_csv(r"C:\王池池\学习\python\活用pandas库\data\survey_visited.csv")
survey=pd.read_csv(r"C:\王池池\学习\python\活用pandas库\data\survey_survey.csv")
print(visited)
print(survey)
visited.merge(survey,left_on='ident',right_on='taken')
(3)用户输入
用户也可以自行创建缺失值,比如依据计算或人工向量来创建向量。对于Series和DataFrame来说,NaN是有效值。
# Series包含缺失值
num_legs=pd.Series({
'goat':4,
'amoeba':nan
})
num_legs
# DataFrame包含缺失值
scientists=pd.DataFrame({
'Name':['Rosaline Franklin','William Gosset'],
'Occupation':['Chemist','Statistician'],
'Born':['1920-07-05','1876-06-13'],
'Died':['1958-04-16','1937-10-16'],
'missing':[NaN,nan]
})
scientists
(3)重建索引
如果想向DataFrame添加新索引,并且希望保留其原始值,需要重建索引。一个常见的使用场景是:在一个DataFrame中,其索引表示某段时间,而我们想向DataFrame中添加更多日期。
gapminder=pd.read_csv(r"...\data\gapminder.tsv",sep='\t')
life_exp=gapminder.groupby(['year'])['lifeExp'].mean()
# 取数据子集,然后调用reindex方法
# 取子集
y2000=life_exp[life_exp.index>2000]
print(y2000)
# 调用reindex方法
print(y2000.reindex(range(2000,2010)))
3、处理缺失数据
(1)查找和统计确实数据
方法1:用count函数统计处理非缺失值的个数,然后用总行数减去不包含缺失值的行数。
方法2:使用isnull方法
方法3:使用value_counts方法
# 导入数据
ebola=pd.read_csv(r"...\data\country_timeseries.csv")
# 方法1
# 统计非缺失值的个数
ebola.count()
# 获得总行数
num_rows=ebola.shape[0]
# 总行数减去非缺失值个数
num_missing=num_rows-ebola.count()
print(num_missing)
# 方法2 isnull方法
ebola.isnull().sum()
ebola['Cases_Guinea'].isnull().sum()
# 方法3
ebola.Cases_Guinea.value_counts(dropna=False).head()
(2)清理缺失数据
①重新编码/替换
使用fillna方法吧缺失值重新编码为其他值。比如把缺失值重新编码为0。如下:
ebola.fillna(0).iloc[0:10,0:5]
②前值填充
对于缺失值,可以使用内置方法做前值填充(fill forward)或者后值填充(fill backward)。做前值填充时,将按照前一个值填充缺失值。如果某一列以缺失值开始,那么前值填充时,该缺失值将会继续存在。
ebola.fillna(method='ffill').iloc[0:10,0:5]
③后值填充
与前值填充类似,如果某一列以缺失值结束,那么该缺失值也将继续存在。
ebola.fillna(method='bfill').iloc[:,0:5].tail()
④插值
插值使用现有值来填充缺失值。填充缺失值的方法有很多种,pandas中的差值方法默认一线性方式填充缺失值。
ebola.interpolate().iloc[0:10,0:5]
⑤删除缺失值
处理缺失数据的另一种方法是删除含有缺失数据的观测值或变量。不同数据集包含的缺失数据数量不同。对于某些数据集,如果只保留完整数据,那么最终得到的数据集可能是无用的。或许缺失数据不是随机的,删除缺失值后,会得到有偏差的数据集。只保留完整数据也可能导致数据不足,而无法开展分析。
pandas中可以使用dropna方法删除缺失数据,并且可以通过设置参数控制删除方式。how参数any(只要包含NA值即删除),all(全为NA才删除)。thresh参数允许在删除行或列之前指定NaN值得数量。
ebola_dropna=ebola.dropna(how='any')
ebola_dropna.shape
(3)缺失值计算
若直接计算中包含缺失值,通常返回缺失值。但如果调用的函数或方法在计算中能忽略缺失值,就另当别论。可以忽略缺失值的内置方法有mean和sum。这些函数通常有skipna参数,通过该参数指定计算时是否要忽略缺失值,通常也是默认忽略。
#缺失值直接参与运算
ebola['Cases_multiple']=ebola['Cases_Guinea']+\
ebola['Cases_Liberia']+ebola['Cases_SierraLeone']
ebola_subset=ebola.loc[:,['Cases_Guinea','Cases_Liberia',\
'Cases_SierraLeone','Cases_multiple']]
ebola_subset.head()
# skipna参数的默认值为True,表示忽略缺失值
print(ebola.Cases_Guinea.sum())
print(ebola.Cases_Guinea.sum(skipna=False))