在做數據清洗等工作時,必不可少的環節就是缺失值處理。在採用pandas讀取或處理數據時,dataframe的缺失值默認是用nan填充的。但大多數情況下,我們需要的是None或者Null值而不是nan.所以,如何替換dataframe中的nan呢?
替換nan的方法有很多,本文總結了三個方法。dataframe.fillna()方法,dataframe.applymap()以及dataframe.where()方法。本文通過測試數據對每個方法進行分析。最終選擇使用哪個方法可結合本文的分析,根據真實場景進行取捨。
1.準備測試數據
types = {'name': str, 'cost': float, 'age': float, 'phone': str}
# 注意age不能指定爲int類型,
# 指定類型讀取數據
data = pd.read_excel('../../test.xlsx', sheet_name='Sheet1', header=0, dtype=types)
#查看數據
print(data)
# 查看每列的數據類型
print(data.dtypes)
注意:age列中含有缺失值,所以不能指定爲int型,否則會報錯:ValueError: Unable to convert column age to type <class 'int'>
輸出結果:
name cost age phone
0 小青 NaN 25.0 12341234123
1 小紅 1.628771e+06 23.0 12341234124
2 小明 8.438553e+05 26.0 12341234125
3 小李 1.699444e+06 25.0 12341234126
4 小王 2.635745e+06 NaN 12341234127
5 小張 1.168142e+06 25.0 nan
6 小劉 1.607670e+06 28.0 12341234129
7 nan 1.234523e+04 27.0 nan
name object
cost float64
age float64
phone object
dtype: object
Process finished with exit code 0
2.dataframe.fillna();該方法使用指定的方法填充NA / NaN值
values = {'name': '', 'cost': 0, 'age': -1, 'phone': ''}
data.fillna(value=values,inplace=True)
print(data)
輸出結果:
name cost age phone
0 小青 0.000000e+00 25.0 12341234123
1 小紅 1.628771e+06 23.0 12341234124
2 小明 8.438553e+05 26.0 12341234125
3 小李 1.699444e+06 25.0 12341234126
4 小王 2.635745e+06 -1.0 12341234127
5 小張 1.168142e+06 25.0 nan
6 小劉 1.607670e+06 28.0 12341234129
7 nan 1.234523e+04 27.0 nan
Process finished with exit code 0
從上面的輸出結果可以看出:fillna()方法必須要指定一個填充且不爲None的值,且object類型的填充並未生效
3.dataframe.applymap()自定義處理方法
data = data.applymap(lambda x: x if str(x) != 'nan' else None)
# 查看數據
print(data)
輸出結果:
name cost age phone
0 小青 NaN 25.0 12341234123
1 小紅 1.628771e+06 23.0 12341234124
2 小明 8.438553e+05 26.0 12341234125
3 小李 1.699444e+06 25.0 12341234126
4 小王 2.635745e+06 NaN 12341234127
5 小張 1.168142e+06 25.0 None
6 小劉 1.607670e+06 28.0 12341234129
7 None 1.234523e+04 27.0 None
Process finished with exit code 0
由上面的輸出結果可以看出:該方法只對字符串類型的數據生效,數值類型的數據又不能起作用了
4.dataframe.where()篩選需要的數據,如果符合要求就返回原始值,如果不符合要求就用參數other的值填充,other的默認值爲numpy.nan
4.1不指定數據類型
data = pd.read_excel('../../test.xlsx', sheet_name='Sheet1', header=0)
data = data.where((data.notna()),None)
# 查看數據
print(data)
輸出結果:
name cost age phone
0 小青 None 25 1.23412e+10
1 小紅 1.62877e+06 23 1.23412e+10
2 小明 843855 26 1.23412e+10
3 小李 1.69944e+06 25 1.23412e+10
4 小王 2.63574e+06 None 1.23412e+10
5 小張 1.16814e+06 25 None
6 小劉 1.60767e+06 28 1.23412e+10
7 None 12345.2 27 None
Process finished with exit code 0
注意:上面代碼中使用where方法時,讀取測試數據並沒有指定name爲str類型,如果指定爲str類型,則pandas讀取該列時缺失值採用字符串'nan'進行填充,data.notna()返回的是True,如果不指定name列的類型,則該列的缺失值使用float類型的numpy.nan填充,data.notna()返回的是False。
4.2 指定數據類型,可自定的where方法的cond參數
types = {'name': str, 'cost': float, 'age': float, 'phone': str}
# 指定類型讀取數據
data = pd.read_excel('../../test.xlsx', sheet_name='Sheet1', header=0, dtype=types)
data = data.where((data.applymap(lambda x: True if str(x) != 'nan' else False)), None)
# 查看數據
print(data)
輸出結果:
name cost age phone
0 小青 None 25 12341234123
1 小紅 1.62877e+06 23 12341234124
2 小明 843855 26 12341234125
3 小李 1.69944e+06 25 12341234126
4 小王 2.63574e+06 None 12341234127
5 小張 1.16814e+06 25 None
6 小劉 1.60767e+06 28 12341234129
7 None 12345.2 27 None