1. 程式人生 > >利用Python進行資料分析——資料清洗與準備

利用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,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,:]

字串操作

(待補充)