1. 缺失數據的表現
對於一些數據,可能某些值是空的,是缺失的。pandas中能夠有多種處理缺失數據的方式。在pandas中,缺失數據的表現是NaN(Not a Number)
,可使用isnull()
函數檢測出是否有數據缺失。算法
In [4]: data = pd.Series(['aaa','bbb',np.nan,'ddd']) In [5]: data Out[5]: 0 aaa 1 bbb 2 NaN 3 ddd dtype: object In [6]: data.isnull() Out[6]: 0 False 1 False 2 True 3 False dtype: bool
isnull返回一個布爾型的對象,這些布爾值表示哪些值是缺失值NaN,該對象返回的類型和原類型同樣。數組
處理缺失數據的方式有多種,常見爲刪除缺失數據與填充缺失數據。函數
2. 丟棄缺失數據
pandas的dropna方法能夠有效的刪除掉缺失數據,對於Series來講,dropna方法返回一個僅含非空數據和索引值的Series:大數據
In [7]: data Out[7]: 0 aaa 1 bbb 2 NaN 3 ddd dtype: object In [8]: data.dropna() Out[8]: 0 aaa 1 bbb 3 ddd dtype: object
對於DataFrame,dropna能夠刪除全部含有空值的行或列,也能夠根據我的刪除指定的行或列,dropna默認會刪除全部含有NaN的行:code
In [17]: df Out[17]: name age area 0 aa 18 北京 1 NaN 18 廣州 2 cc 20 NaN In [18]: df.dropna() Out[18]: name age area 0 aa 18 北京
傳入how='all',那麼dropna只會刪除一行全是缺失值的行:對象
In [19]: df.loc[3]=[np.nan,np.nan,np.nan] In [20]: df Out[20]: name age area 0 aa 18.0 北京 1 NaN 18.0 廣州 2 cc 20.0 NaN 3 NaN NaN NaN In [21]: df.dropna(how='all') Out[21]: name age area 0 aa 18.0 北京 1 NaN 18.0 廣州 2 cc 20.0 NaN
若是要刪除有缺失值的一列,只須要傳入axis=1:索引
In [25]: df['avg'] = [20,30,40,50] In [26]: df Out[26]: name age area avg 0 aa 18.0 北京 20 1 NaN 18.0 廣州 30 2 cc 20.0 NaN 40 3 NaN NaN NaN 50 In [27]: df.dropna(axis=1) Out[27]: avg 0 20 1 30 2 40 3 50
一樣,dropna(axis=1,how='all')
只會刪除整列都是缺失值的那一列。
若是想留下部分含有缺失值的數據做爲觀察,或者說只想刪除部分數據,那麼就須要使用thresh參數了,保留至少有n個非NaN數據的行/列:開發
In [52]: df Out[52]: name age area avg 0 aa 18.0 北京 20 # 這一行4個值都不是NaN值,非NaN值爲4 1 NaN 18.0 廣州 30 # 有1個NaN值,非NaN值爲3 2 cc 20.0 NaN 40 # 有1個NaN值,非NaN值爲3 3 NaN NaN NaN 50 # 有3個NaN值,非NaN值爲1 In [53]: df.dropna(thresh=4) # 選取非空值至少有4個的行 Out[53]: name age area avg 0 aa 18.0 北京 20 In [54]: df.dropna(thresh=2) Out[54]: name age area avg 0 aa 18.0 北京 20 1 NaN 18.0 廣州 30 2 cc 20.0 NaN 40 In [55]: df.dropna(thresh=4,axis=1) # 選取非空值至少有4個的列 Out[55]: avg 0 20 1 30 2 40 3 50
3. 填充缺失數據
對於缺失數據不想丟棄而想填充新的數據,fillna()
方法也許是首要選擇。經過一個常數調用fillna就會將缺失值替換爲那個常數值:字符串
In [62]: df Out[62]: name age area avg 0 aa 18.0 北京 20 1 NaN 18.0 廣州 30 2 cc 20.0 NaN 40 3 NaN NaN NaN 50 In [64]: df.fillna(0) Out[64]: name age area avg 0 aa 18.0 北京 20 1 0 18.0 廣州 30 2 cc 20.0 0 40 3 0 0.0 0 50
如果經過一個字典調用fillna,就能夠實現對不一樣的列填充不一樣的值:數據分析
In [61]: df.fillna({'name':'dd','age':22,'area':'深圳'}) Out[61]: name age area avg 0 aa 18.0 北京 20 1 dd 18.0 廣州 30 2 cc 20.0 深圳 40 3 dd 22.0 深圳 50
fillna默認會返回新對象,但也能夠對現有對象進行就地修改:
In [65]: df.fillna(0,inplace=True) In [66]: df Out[66]: name age area avg 0 aa 18.0 北京 20 1 0 18.0 廣州 30 2 cc 20.0 0 40 3 0 0.0 0 50
數據中也有可能出現多行數據重複的狀況,DataFrame的duplicated方法返回一個布爾型的對象,表示各行是不是重複的行,它每次都會對比前面出現的行,若是出現與前面出現的行同樣的行,那麼這一行就是重複行:
In [68]: data Out[68]: k1 k2 0 one 1 1 two 1 2 one 2 3 two 3 4 one 3 5 two 4 6 two 4 # 這一行與前一行重複,因爲這一行在第5行後,因此會被判斷爲重複行 In [69]: data.duplicated() Out[69]: 0 False 1 False 2 False 3 False 4 False 5 False 6 True dtype: bool
而drop_duplicates方法
,它會返回一個DataFrame,重複的數組會標爲False而且刪除:
In [70]: data.drop_duplicates() Out[70]: k1 k2 0 one 1 1 two 1 2 one 2 3 two 3 4 one 3 5 two 4
上面兩個方法默認會判斷所有列,若是隻想根據一列進行重複值判斷,能夠傳入包含列索引的列表:
In [75]: data Out[75]: k1 k2 v1 0 one 1 0 1 two 1 1 2 one 2 2 3 two 3 3 4 one 3 4 5 two 4 5 6 two 4 6 In [76]: data.drop_duplicates(['k1']) Out[76]: k1 k2 v1 0 one 1 0 1 two 1 1
duplicated和drop_duplicates默認保留的是第一個出現的值組合。傳入keep='last'則保留最後一個:
In [51]: data.drop_duplicates(['k1', 'k2'], keep='last') Out[51]: k1 k2 v1 0 one 1 0 1 two 1 1 2 one 2 2 3 two 3 3 4 one 3 4 6 two 4 6
有的時候需求是將數據框的某個值替換掉,pandas提供了replace方法,注意它與字符串的replace方法不同。
pandas的replace方法操做的對象是DataFrame的值。
In [83]: data Out[83]: age name 0 -20 小明 1 20 老王 2 23 蘋果 In [84]: data.replace(-20,0) # 將-20替換爲0 Out[84]: age name 0 0 小明 1 20 老王 2 23 蘋果
若是要讓替換值有不一樣的值,要傳入一個列表
In [88]: data.replace(['小明','老王'],['獼猴桃','西瓜']) Out[88]: age name 0 -20 獼猴桃 1 20 西瓜 2 23 蘋果
替換多個值:
In [90]: data.replace(['小明','老王'],'蘋果') Out[90]: age name 0 -20 蘋果 1 20 蘋果 2 23 蘋果
假若有以下數據:
In [94]: data Out[94]: position avg brief 0 Java開發 10 ['開發','工程師','高新'] 1 數據分析師 13 ['分析師','大數據'] 2 算法工程師 15 ['算法','數學']
需求是在avg的列的值加上字母k,去掉brief列的值的方括號和單引號。pandas中有不少種方法能夠實現,下面介紹一種簡單的方法。
+k需求:
In [98]: data.avg Out[98]: 0 10 1 13 2 15 Name: avg, dtype: int64 In [99]: data.avg.astype('str')+'k' Out[99]: 0 10k 1 13k 2 15k Name: avg, dtype: object In [100]: data['avg'] = data.avg.astype('str')+'k' In [101]: data Out[101]: position avg brief 0 Java開發 10k ['開發','工程師','高新'] 1 數據分析師 13k ['分析師','大數據'] 2 算法工程師 15k ['算法','數學']
去除方括號和去除單引號需求:
In [104]: data.brief Out[104]: 0 ['開發','工程師','高新'] 1 ['分析師','大數據'] 2 ['算法','數學'] Name: brief, dtype: object In [105]: data.brief.str[1:-1] Out[105]: 0 '開發','工程師','高新' 1 '分析師','大數據' 2 '算法','數學' Name: brief, dtype: object In [106]: data.brief.str[1:-1].str.replace("'","") Out[106]: 0 開發,工程師,高新 1 分析師,大數據 2 算法,數學 Name: brief, dtype: object