利用Python進行資料分析——資料清洗與準備
import numpy as np
import pandas as pd
處理缺失資料
丟棄含缺失值的行列
預設的dropna()方法會丟棄所有含缺失值的行:
frame=pd.DataFrame([[1,6.5,None],[1,None,None],
[None,None,None],[6.5,3,None]])
cleaned=frame.dropna()
frame
cleaned
可以指定丟棄缺失值的方式,當只有一行或一列全部是缺失值時才進行丟棄:
data_1=frame.dropna(how='all' ,axis=0) #丟棄全為空值的行
data_1
data_2=frame.dropna(how='all',axis=1) #丟棄全為空值的列
data_2
還可以指定丟棄資料的上限值,pandas會優先丟棄擁有更多缺失值的行:
data_3=frame.dropna(thresh=2)
data_3
填充缺失值
可以使用fillna()方法來填充缺失值:
frame.fillna(0)
可以給fillna()傳遞一個字典來顯示說明對某一列填充的值:
frame.fillna({
0:0,
1:1,
2:2
} )
使用前面的值來對缺失值進行插值:
frame.fillna(method='ffill')
使用統計數字對缺失值進行填充:
···
frame.iloc[:,0].fillna(frame.iloc[:,0].median()) #中位數填充
···
frame.iloc[:,1].fillna(frame.iloc[:,1].mean()) #均值填充
資料轉換
移除重複資料
frame=pd.DataFrame({
'C1':['one','two']*2+['two'],
'C2':[1,1,2,3,3 ]
})
frame
frame.drop_duplicates() #丟棄重複的最後一行
也可指定列丟棄重複的行:
frame.drop_duplicates(['C1'])
對映
可以使用map()方法根據已有的資料按照指定的對映關係生成新資料:
frame=pd.DataFrame({
'food':['bacon','pulled pork','bacon','Pastrami','corned beef','Bacon','pastrami','honey ham','nova lox'],
'ounces':[4,3,12,6,7.5,8,3,5,6]
})
frame
指定對映關係:
meat2animal={
'bacon':'pig',
'pulled pork':'pig',
'pastrami':'cow',
'corned beef':'cow',
'honey ham':'pig',
'nova lox':'salmon'
}
因為原DF中有大小寫,所以應用map()方法之前需要轉換成小寫:
frame['animal']=frame.loc[:,'food'].str.lower().map(meat2animal)
frame
值的替換
假設在資料中存在非常明顯的異常值,則這些資料可能是被填充過的。比如下面的資料,其中的-999很可能是代表著缺失值,在資料還原的時候可以將其替換成缺失值。
obj=pd.Series([1,-999,2,3,4,-999])
obj.replace([-999],[None])
也可以用字典的形式進行替換:
replace_map={
-999:None
}
obj.replace(replace_map)
行列標籤的更改
同資料一樣,行列標籤也可以用函式或對映來更改。
frame=pd.DataFrame(
np.arange(12).reshape((3,4)),
index=['Ohio','Colorado','New York'],
columns=['one','two','three','four']
)
frame
index_trans=lambda x:x[:4].upper()
frame.index.map(index_trans)
Index([‘OHIO’, ‘COLO’, ‘NEW ‘], dtype=’object’)
對於單個或少數行列標籤的修改,使用rename()方法更方便:
frame.rename(
index={'Ohio':'Indiana'},
columns={'three':'peekaboo'},
inplace=True
)
frame
資料的離散化
ages=[20,22,25,27,21,23,37,31,61,45,41,32]
bins=[18,25,35,60,100] #五個分割點將資料分成4個區間
group_names=['Youth','YoungAdult','MiddleAged','Senior']
cats=pd.cut(ages,bins,labels=group_names)
cats.value_counts()
Youth 5
YoungAdult 3
MiddleAged 3
Senior 1
dtype: int64
還可以直接指定分割區間數:
data=np.random.randn(20)
cats=pd.cut(data,4) #將區間平均分成4個子區間
cats.value_counts()
(-1.679, -0.908] 3
(-0.908, -0.14] 5
(-0.14, 0.628] 7
(0.628, 1.396] 5
dtype: int64
cut()方法是按區間的取值範圍將區間劃分成子區間,qcut()方法是按照樣本的分位數來進行劃分,qcut()方法保證每個子區間都擁有同樣數量的樣本:
data=np.random.randn(100)
cats=pd.qcut(data,[0,0.1,0.5,0.9,1]) #指定百分位數
cats.value_counts()
(-2.492, -1.21] 10
(-1.21, 0.0562] 40
(0.0562, 1.231] 40
(1.231, 2.355] 10
dtype: int64
data=np.random.randn(100)
cats=pd.qcut(data,4) #指定子區間數
cats.value_counts()
(-1.9609999999999999, -0.424] 25
(-0.424, -0.012] 25
(-0.012, 0.581] 25
(0.581, 2.144] 25
dtype: int64
異常值
考慮一個服從標準正態分佈的資料集,根據原則,可以將絕對值大於3的值視為異常值,將資料集中的值截斷到[-3,3]的範圍內:
data=pd.DataFrame(np.random.randn(1000,3))
data.describe()
將異常值截斷為-3或3:
data[(np.abs(data)>3)]=np.sign(data)*3
data.describe()
資料重排與隨機取樣
在機器學習專案中,資料重排常用於打亂資料集,然後劃分訓練集與測試集;而隨機取樣通常用於生成小批量的訓練資料集。
frame=pd.DataFrame(np.arange(20).reshape((5,4)))
re_order=np.random.permutation(frame.shape[0])
training_set=frame.iloc[re_order[:3],:]
test_set=frame.iloc[re_order[3:],:]
mini_batch=training_set.sample(1,replace=True)
training_set
test_set
mini_batch
啞變數
在機器學習專案中,有時需要對變數進行獨熱編碼或生成啞變數以增加系統的非線性。
frame=pd.DataFrame({
'key':['b','b','a','c']
})
dummies=pd.get_dummies(frame.loc[:,'key'],prefix='key')
dummies
對於某些資料可能同時具有多個同類屬性,如電影資料,一部電影可能同時屬於愛情片和動作片是可能的。這種資料的轉換稍稍麻煩一點:
movies=pd.read_table('datasets/movielens/movies.dat',sep='::',header=None,names=['id','title','genre'],engine='python')
movies.sample(3)
首先將所有的電影型別全部抽取出來:
genres=[]
for genre in movies.iloc[:,2]:
genres.extend(genre.split('|'))
genres=pd.unique(genres)
genres
再生成一個對應形狀的空矩陣:
dummies=pd.DataFrame(np.zeros((movies.shape[0],len(genres))),columns=genres,dtype=int)
利用原資料的資訊,將dummies資料集中相應的位置置1:
for row_index,genre in enumerate(movies.iloc[:,2]):
col_index=dummies.columns.get_indexer(genre.split('|'))
dummies.iloc[row_index,col_index]=1
將啞變數資料加入到原資料集中:
new_data=movies.join(dummies)
new_data.iloc[0,:]
字串操作
(待補充)