利用Python Pandas進行資料預處理-資料清洗
資料缺失、檢測和過濾異常值、移除重複資料
資料缺失
資料缺失在大部分資料分析應用中都很常見,Pandas使用浮點值NaN表示浮點和非浮點陣列中的缺失資料,他只是一個便於被檢測出來的資料而已。
from pandas import Series,DataFrame
string_data=Series(['abcd','efgh','ijkl','mnop'])
print(string_data)
print("...........\n")
print(string_data.isnull())
Python內建的None值也會被當作NA處理
from pandas import Series,DataFrame
string_data=Series(['abcd','efgh','ijkl','mnop'])
print(string_data)
print("...........\n")
string_data[0]=None
print(string_data.isnull())
處理NA的方法有四種:dropna,fillna,isnull,notnull
is(not)null,這一對方法對物件做出元素級的應用,然後返回一個布林型陣列,一般可用於布林型索引。
dropna,對於一個Series,dropna返回一個僅含非空資料和索引值的Series。
問題在於DataFrame的處理方式,因為一旦drop的話,至少要丟掉一行(列)。這裡解決方法與前面類似,還是通過一個額外的引數:dropna(axis=0,how=’any’,thresh=None),how引數可選的值為any或者all.all僅在切片元素全為NA時才拋棄該行(列)。thresh為整數型別,eg:thresh=3,那麼一行當中至少有三個NA值時才將其保留。
fillna,fillna(value=None,method=None,axis=0)中的value除了基本型別外,還可以使用字典,這樣可以實現對不同列填充不同的值。
過濾資料:
對於一個Series,dropna返回一個僅含非空資料和索引值的Series:
from pandas import Series,DataFrame
from numpy import nan as NA
data=Series([1,NA,3.5,NA,7])
print(data.dropna())
另一個過濾DataFrame行的問題涉及問題序列資料。假設只想留一部分觀察資料,可以用thresh引數實現此目的:
from pandas import Series,DataFrame, np
from numpy import nan as NA
data=DataFrame(np.random.randn(7,3))
data.ix[:4,1]=NA
data.ix[:2,2]=NA
print(data)
print("...........")
print(data.dropna(thresh=2))
不想濾除缺失的資料,而是通過其他方式填補“空洞”,fillna是最主要的函式。
通過一個常數呼叫fillna就會將缺失值替換為那個常數值:
from pandas import Series,DataFrame, np
from numpy import nan as NA
data=DataFrame(np.random.randn(7,3))
data.ix[:4,1]=NA
data.ix[:2,2]=NA
print(data)
print("...........")
print(data.fillna(0))
若是通過一個字典呼叫fillna,就可以實現對不同列填充不同的值。
from pandas import Series,DataFrame, np
from numpy import nan as NA
data=DataFrame(np.random.randn(7,3))
data.ix[:4,1]=NA
data.ix[:2,2]=NA
print(data)
print("...........")
print(data.fillna({1:111,2:222}))
可以利用fillna實現許多別的功能,比如可以傳入Series的平均值或中位數:
from pandas import Series,DataFrame, np
from numpy import nan as NA
data=Series([1.0,NA,3.5,NA,7])
print(data)
print("...........\n")
print(data.fillna(data.mean()))
檢測和過濾異常值
異常值(outlier)的過濾或變換運算在很大程度上就是陣列運算。如下一個(1000,4)的標準正態分佈陣列:
from pandas import Series,DataFrame, np
from numpy import nan as NA
data=DataFrame(np.random.randn(1000,4))
print(data.describe())
print("\n....找出某一列中絕對值大小超過3的項...\n")
col=data[3]
print(col[np.abs(col) > 3] )
print("\n....找出全部絕對值超過3的值的行...\n")
print(col[(np.abs(data) > 3).any(1)] )
移除重複資料
DataFrame的duplicated方法返回一個布林型Series,表示各行是否是重複行。
from pandas import Series,DataFrame, np
from numpy import nan as NA
import pandas as pd
import numpy as np
data=pd.DataFrame({'k1':['one']*3+['two']*4, 'k2':[1,1,2,2,3,3,4]})
print(data)
print("........\n")
print(data.duplicated())
與此相關的還有一個drop_duplicated方法,它用於返回一個移除了重複行的DataFrame:
from pandas import Series,DataFrame, np
from numpy import nan as NA
import pandas as pd
import numpy as np
data=pd.DataFrame({'k1':['one']*3+['two']*4, 'k2':[1,1,2,2,3,3,4]})
print(data)
print("........\n")
print(data.drop_duplicates())
上面的兩個方法會預設判斷全部列,也可以指定部分列進行重複項判斷,假設還有一列值,而只希望根據k1列過濾重複項。
from pandas import Series,DataFrame, np
from numpy import nan as NA
import pandas as pd
import numpy as np
data=pd.DataFrame({'k1':['one']*3+['two']*4, 'k2':[1,1,2,2,3,3,4]})
data['v1']=range(7)
print(data)
print("........\n")
print(data.drop_duplicates(['k1']))
duplicates和drop_duplicates預設保留第一個出現的值組合。傳入take_last=True則保留最後一個:
from pandas import Series,DataFrame, np
from numpy import nan as NA
import pandas as pd
import numpy as np
data=pd.DataFrame({'k1':['one']*3+['two']*4, 'k2':[1,1,2,2,3,3,4]})
data['v1']=range(7)
print(data)
print("........\n")
print(data.drop_duplicates(['k1','k2'],take_last=True))