數(shù)據(jù)預(yù)處理包括數(shù)據(jù)的清洗坊罢、合并、重塑與轉(zhuǎn)換知市,解決數(shù)據(jù)缺失傻盟、極端值、數(shù)據(jù)格式不統(tǒng)一等問(wèn)題嫂丙,本文通過(guò)介紹Pandas中專(zhuān)門(mén)用于進(jìn)行數(shù)據(jù)預(yù)處理的函數(shù)及方法來(lái)進(jìn)行數(shù)據(jù)預(yù)處理的標(biāo)準(zhǔn)流程娘赴。
0. 數(shù)據(jù)清洗
數(shù)據(jù)清洗是一項(xiàng)復(fù)雜的工作,該過(guò)程目的在于提高數(shù)據(jù)的質(zhì)量跟啤,將臟數(shù)據(jù)清理干凈诽表,使數(shù)據(jù)具有完整性、唯一性隅肥、權(quán)威性竿奏、合法性、一致性等特點(diǎn)腥放。Pandas常見(jiàn)的數(shù)據(jù)清洗操作有空值和缺失值的處理泛啸、重復(fù)值的處理、異常值的處理秃症、統(tǒng)一數(shù)據(jù)格式等候址。
0.1 空值和缺失值的處理
空值一般表示數(shù)據(jù)未知、不適用或?qū)⒃谝院筇砑訑?shù)據(jù)种柑。缺失值是指數(shù)據(jù)集中某個(gè)或某些屬性不完整主要原因有機(jī)械原因和人為原因岗仑,機(jī)械原因往往因?yàn)闄C(jī)器故障而人為原因可能由于人為隱瞞或錄入失誤而引起的【矍耄空值使用None
表示荠雕,缺失值使用NaN
表示,處理空值和缺失值通常有如下四個(gè)函數(shù):
函數(shù)名 | 函數(shù)效果 |
---|---|
isnull() |
檢查空值或缺失值 |
notnull() |
檢查空值或缺失值 |
dropna() |
刪除含有空值或缺失值的行或列 |
fillna() |
填充空值或缺失值 |
0.1.1 isnull()
和notnull()
isnull()
和notnull()
參數(shù)都是只有一個(gè)良漱,表示檢查空值對(duì)象舞虱,不同之處在于isnull()
如果檢測(cè)到None
或NaN
則標(biāo)記為True
而notnull()
檢測(cè)到None
或NaN
則標(biāo)記為False
,例如:
import pandas as pd
from numpy import NaN
data = pd.DataFrame(
[[1, 2, 3, NaN], [2, 4, NaN, NaN], [NaN, NaN, NaN, NaN], [1, 2, 6, 7]],
columns=['A', 'B', 'C', 'D'])
print(data)
print(pd.isnull(data))
print(pd.notnull(data))
輸出:
A B C D
0 False True False True
1 False False False True
2 False True False False
3 True False False True
A B C D
0 True False True False
1 True True True False
2 True False True True
3 False True True False
0.1.2 dropna()
該方法作用是刪除含有空值或缺失值的行或列母市。
語(yǔ)法:
pandas.dropna(axis=0,how='any',thresh=None,subset=None,inplace=False)
-
axis
:確定過(guò)濾行的行或列矾兜,默認(rèn)為0
。取值為0
或index
時(shí)刪除包含缺失值或空值的行患久;取值為1
或columns
時(shí)刪除包含缺失值或空值的列椅寺。 -
how
:確定過(guò)濾的標(biāo)準(zhǔn)浑槽,默認(rèn)為any
,取值為any
時(shí),則存在NaN
或None
則刪除該行或該列返帕;取值為all
時(shí)桐玻,則所有值都為NaN
或None
是才刪除該行或該列。 -
thresh
:表示有效數(shù)據(jù)的最小要求荆萤,如果傳入了2镊靴,則是要求該行或該列至少有兩個(gè)非NaN
或None
時(shí)將其保留。 -
subset
:表示在特定子集中的尋找NaN
或None
-
inplace
:表示是否在原數(shù)據(jù)上操作默認(rèn)為False
链韭,如果設(shè)為True
則在原數(shù)據(jù)操作偏竟,如果設(shè)為False
則修改原數(shù)據(jù)的副本返回新的數(shù)據(jù)。
實(shí)例:
import pandas as pd
from numpy import NaN
data = pd.DataFrame(
[[1, 2, 3, NaN], [2, 4, NaN, NaN], [NaN, NaN, NaN, NaN], [1, 2, 6, 7]],
columns=['A', 'B', 'C', 'D'])
# 默認(rèn)參數(shù)
print(data.dropna())
# 當(dāng)一行/列全部都為NaN時(shí)刪除該行/列
print("\n", data.dropna(how='all'))
# 直接對(duì)原始數(shù)據(jù)操作
data.dropna(inplace=True)
print("\n修改后的數(shù)據(jù)為:\n", data)
輸出為:
A B C D
3 1.0 2.0 6.0 7.0
A B C D
0 1.0 2.0 3.0 NaN
1 2.0 4.0 NaN NaN
3 1.0 2.0 6.0 7.0
修改后的數(shù)據(jù)為:
A B C D
3 1.0 2.0 6.0 7.0
0.1.3 fillna()
該方法可實(shí)現(xiàn)空值或缺失值的填充敞峭。
語(yǔ)法:
pandas.fillna(value=None,methon=None,axis=None,inplace=False,limit=None,downcast=None,**kwargs)
-
value
:用于填充的數(shù)值 -
methon
:表示填充方式踊谋,默認(rèn)為None
另外支持一下取值-
pad/ffill
:將最后一個(gè)有效數(shù)據(jù)向后傳播,也就是說(shuō)用缺失值前面的一個(gè)值代替缺失值旋讹。 -
backfill/bfill
:將最后一個(gè)有效值向前傳播殖蚕,也就是說(shuō)用缺失值后面的一個(gè)值代替缺失值。
-
-
limit
:可以連續(xù)填充的最大數(shù)據(jù)量沉迹,默認(rèn)為None
注意:
method
和value
參數(shù)不能同時(shí)使用睦疫。
實(shí)例:
import pandas as pd
from numpy import NaN
data = pd.DataFrame(
[[1, 2, 3, NaN], [2, 4, NaN, NaN], [NaN, NaN, NaN, NaN], [1, 2, 6, 7]],
columns=['A', 'B', 'C', 'D'])
# 常數(shù)填充缺失值
print("用常數(shù)6填充缺失值:\n", data.fillna(value="6"))
# 向下填充缺失值(前向填充)
print("\n前向填充缺失值:\n", data.fillna(method="ffill"))
# 指定列填充缺失值
print("\n用常數(shù)10填充A列缺失值,用常數(shù)20填充B列缺失值:\n", data.fillna({'A': 10, 'B': 20}))
輸出為:
用常數(shù)6填充缺失值:
A B C D
0 1 2 3 6
1 2 4 6 6
2 6 6 6 6
3 1 2 6 7
前向填充缺失值:
A B C D
0 1.0 2.0 3.0 NaN
1 2.0 4.0 3.0 NaN
2 2.0 4.0 3.0 NaN
3 1.0 2.0 6.0 7.0
用常數(shù)10填充A列缺失值胚股,用常數(shù)20填充B列缺失值:
A B C D
0 1.0 2.0 3.0 NaN
1 2.0 4.0 NaN NaN
2 10.0 20.0 NaN NaN
3 1.0 2.0 6.0 7.0
0.2 重復(fù)值的處理
當(dāng)數(shù)據(jù)中出現(xiàn)了重復(fù)值笼痛,大多數(shù)情況需要?jiǎng)h除裙秋,例如下表中:
id | name | height | sex | |
---|---|---|---|---|
0 | 1 | zz | 160 | 男 |
1 | 2 | yxy | 160 | 男 |
2 | 3 | zxy | 170 | 女 |
3 | 4 | wcc | 170 | 男 |
4 | 4 | wcc | 170 | 男 |
顯然索引為3
和4
的數(shù)據(jù)完全相同需要進(jìn)行刪除琅拌,對(duì)于重復(fù)值的處理,Pandas提供了以下兩個(gè)函數(shù):
函數(shù) | 函數(shù)效果 |
---|---|
duplicated() |
標(biāo)記是否有重復(fù)值 |
drop_duplicates() |
刪除重復(fù)值 |
0.2.1 duplicated()
重復(fù)值標(biāo)記函數(shù)
語(yǔ)法:
duplicated(subset=None,keep='first')
-
subset
:用于識(shí)別重復(fù)的列標(biāo)簽或列標(biāo)簽序列摘刑,默認(rèn)識(shí)別所有列標(biāo)簽进宝。 -
keep
:刪除重復(fù)值并保留第一次出現(xiàn)的項(xiàng),取值如下:-
first
:從前向后查找枷恕,除了第一次出現(xiàn)的項(xiàng)其余相同的均標(biāo)記為重復(fù)党晋。(默認(rèn)值) -
last
:從后往前查找,除了最后一次出現(xiàn)的項(xiàng)其余相同的均標(biāo)記為重復(fù)徐块。 -
False
:所有相同的標(biāo)記均標(biāo)記為重復(fù)未玻。
-
實(shí)例:
import pandas as pd
data = pd.DataFrame(
[[1, 'zz', 160, '男'], [2, 'yxy', 160, '男'], [3, 'zxy', 170, '女'],
[4, 'wcc', 170, '男'], [4, 'wcc', 170, '男']],
columns=['id', 'name', 'height', 'sex'])
data_p = pd.DataFrame([
data.duplicated(),
data.duplicated(keep="last"),
data.duplicated(['height'])
],
index=['無(wú)參數(shù)', '從后向前查找', '指定height列'])
print(data_p)
輸出為:
0 1 2 3 4
無(wú)參數(shù) False False False False True
從后向前查找 False False False True False
指定height列 False True False True True
0.2.2 drop_duplicates()
重復(fù)值刪除函數(shù)
語(yǔ)法:
drop_duplicates(subset=None,keep="first",inplace=False)
實(shí)例:
import pandas as pd
data = pd.DataFrame(
[[1, 'zz', 160, '男'], [2, 'yxy', 160, '男'], [3, 'zxy', 170, '女'],
[4, 'wcc', 170, '男'], [4, 'wcc', 170, '男']],
columns=['id', 'name', 'height', 'sex'])
print(data.drop_duplicates())
輸出為:
id name height sex
0 1 zz 160 男
1 2 yxy 160 男
2 3 zxy 170 女
3 4 wcc 170 男
0.3 異常值的處理
異常值指的是樣本中的個(gè)別值,其數(shù)值明顯偏離它所屬樣本的其余觀測(cè)值:
如圖胡控,藍(lán)色圈出來(lái)的點(diǎn)明顯高于其他值扳剿。對(duì)于異常值的檢測(cè)通常使用3σ原則(拉依達(dá)準(zhǔn)則)
或箱型圖
檢測(cè)。
0.3.1 基于3σ原則
檢測(cè)異常值
3σ原則又稱(chēng)拉依達(dá)原則昼激,它是指假設(shè)一組檢測(cè)數(shù)據(jù)中只含有隨機(jī)誤差庇绽,對(duì)其進(jìn)行計(jì)算處理得到標(biāo)準(zhǔn)偏差锡搜,按一定概率確定一個(gè)區(qū)間,凡是超過(guò)這個(gè)區(qū)間的誤差都是粗大誤差瞧掺,在此誤差范圍內(nèi)的數(shù)據(jù)應(yīng)予以剔除耕餐,在正態(tài)分布概率公式中,σ
表示標(biāo)準(zhǔn)差辟狈,μ
表示平均數(shù),f(x)
表示正態(tài)分布函數(shù)肠缔,表達(dá)式如下:
其中正態(tài)函數(shù)的分布函數(shù)圖如下所示:
- 數(shù)值分布在(
μ-σ
,μ+σ
)中的概率為68.27% - 數(shù)值分布在(
μ-2σ
哼转,μ+2σ
)中的概率為95.44% - 數(shù)值分布在(
μ-3σ
桩砰,μ+3σ
)中的概率為99.70%
通過(guò)3σ
原則,可以定義如下函數(shù):
import numpy as np
# ser1表示傳入DataFrame的某一列
def three_sigma(ser1):
# 求平均值
mean_value = ser1.mean()
# 求標(biāo)準(zhǔn)差
std_value = ser1.std()
# 位于(μ-3σ,μ+3σ)區(qū)間內(nèi)的數(shù)據(jù)是正常的释簿,不在該區(qū)間的數(shù)據(jù)是異常的
# ser1中的數(shù)值小于μ-3σ或大于μ+3σ均為異常值
# 一旦發(fā)現(xiàn)異常值就標(biāo)注為T(mén)rue亚隅,否則標(biāo)注為False
rule = (mean_value - 3 * std_value > ser1) | (mean_value + 3 * std_value < ser1)
# 返回異常值的位置索引
index = np.arange(ser1.shape[0])[rule]
# 獲取異常數(shù)據(jù)
outrange = ser1.iloc[index]
return(outrange)
對(duì)于一組數(shù)據(jù)例如:1,2,3,4,5,1000,2,3,4,5,3,8,23,12,66
,通過(guò)3σ原則
來(lái)進(jìn)行檢測(cè):
import pandas as pd
data = pd.DataFrame({"A": [1, 2, 3, 4, 5, 1000, 2, 3, 4, 5, 3, 8, 23, 12, 66]})
print(three_sigma(data['A']))
檢測(cè)結(jié)果為:
5 1000
Name: A, dtype: int64
0.3.2 基于箱型圖檢測(cè)異常值
箱型圖是一種用作顯示一組數(shù)據(jù)分散情況的統(tǒng)計(jì)圖庶溶,在箱型圖中煮纵,異常值被定義為小于Ql-1.5IQR或大于Qu+1.5IQR的值。其中:
- Ql稱(chēng)為下四分位數(shù)偏螺,表示全部觀察值中有四分之一的數(shù)據(jù)取值比他小
- Qu稱(chēng)為上四分位數(shù)行疏,表示全部觀察值中有四分之一的數(shù)據(jù)取值比他大
- IQR稱(chēng)為四分位數(shù)的間距,是上四分位數(shù)Qu與下四分位數(shù)Ql之差套像,其間包含了全部觀察值的一半酿联。
離散點(diǎn)表示的是異常值,上界表示除異常值以外數(shù)據(jù)中最大值夺巩;下界表示除異常值以外數(shù)據(jù)中最小值贞让。
箱型圖根據(jù)實(shí)際的數(shù)據(jù)進(jìn)行繪制,對(duì)數(shù)據(jù)沒(méi)有任何要求柳譬,箱型圖判斷異常值的標(biāo)準(zhǔn)是以四分位數(shù)和四分位距為基礎(chǔ)喳张。在Pandas中提供了一個(gè)boxplot()
方法用于繪制箱型圖:
import pandas as pd
import matplotlib.pyplot as plt
data = pd.DataFrame({
'A': [1, 2, 3, 4],
'B': [2, 3, 5, 2],
'C': [1, 4, 7, 4],
'D': [1, 5, 30, 3]
})
data.boxplot(column=['A', 'B', 'C', 'D'])
plt.show()
使用
vscode
或pycharm
進(jìn)行可視化需要使用繪圖庫(kù),如果需要直接顯示可以通過(guò)使用Jupyter
進(jìn)行快速編輯美澳,安裝教程如下:通過(guò)在
Jupyter
中輸入:import pandas as pd data = pd.DataFrame({ 'A': [1, 2, 3, 4], 'B': [2, 3, 5, 2], 'C': [1, 4, 7, 4], 'D': [1, 5, 30, 3] }) data.boxplot(column=['A', 'B', 'C', 'D'])
即可達(dá)到實(shí)時(shí)顯示的目的:
可以看出根據(jù)檢出結(jié)果異常值被檢測(cè)出,對(duì)于異常值制跟,通常會(huì)使用以下四種方式處理異常值:
- 刪除異常值記錄
- 使用具體值進(jìn)行替換舅桩,例如使用前后兩個(gè)觀測(cè)值的平均值進(jìn)行修正
- 不處理,直接在具有異常值的數(shù)據(jù)集中統(tǒng)計(jì)分析
- 視為缺失值雨膨,利用缺失值的處理方法修正異常值
如果需要對(duì)異常值進(jìn)行替換擂涛,可以使用replace()
函數(shù)。
replace()
函數(shù)語(yǔ)法:
replace(to_replace=None,value=None,inplace=False,limit=None,regex=False,method='pad')
-
to_replace
:表示查找被替換的方式 -
value
:用來(lái)替換任何匹配to_replace
的值哥放,默認(rèn)為None
-
limit
:表示前向或后向填充的最大尺寸間隙 -
regex
:接收布爾值或與to_replace
相同的類(lèi)型歼指,默認(rèn)為False
爹土,表示是否將to_replace
和value
解釋為正則表達(dá)式。
實(shí)例:
import pandas as pd
data = pd.DataFrame({
'A': [1, 2, 3, 4],
'B': [2, 3, 5, 2],
'C': [1, 4, 7, 4],
'D': [1, 5, 30, 3]
})
data.replace(to_replace=30, value=3, inplace=True)
print(data)
通過(guò)replace
方法將data
中的異常值30
直接在原數(shù)據(jù)集中替換為3
踩身,注意胀茵,replace()
方法中的to_replace
參數(shù)的傳入值也可為列表list
輸出:
A B C D
0 1 2 1 1
1 2 3 4 5
2 3 5 7 3
3 4 2 4 3
0.4 更改數(shù)據(jù)類(lèi)型
在處理數(shù)據(jù)時(shí)可能會(huì)遇到數(shù)據(jù)類(lèi)型不一致的問(wèn)題,對(duì)于數(shù)據(jù)類(lèi)型的統(tǒng)一有如下三種方式:
- 創(chuàng)建時(shí)指定數(shù)據(jù)類(lèi)型
-
astype()
方法 -
numberic()
方法
0.4.1 創(chuàng)建時(shí)指定數(shù)據(jù)類(lèi)型
使用dtype
參數(shù)挟阻,例如:
import pandas as pd
data = pd.DataFrame({"A": ['1', '2', '3'], "B": ['4', '5', '6']}, dtype='int')
print(data.dtypes)
可以看出輸入的對(duì)象是字符型巩步,但是通過(guò)指定dtype
最終的對(duì)象為int
型驻民。
A int32
B int32
dtype: object
0.4.2 astype()
方法
語(yǔ)法:
astype(dtype,copy=True,errors='raise',** kwargs)
-
dtype
:數(shù)據(jù)類(lèi)型 -
copy
:是否建立副本好渠,默認(rèn)為True
-
errors
:錯(cuò)誤采取的處理方式文虏,默認(rèn)為raise
(允許引發(fā)異常),還可以設(shè)置為ignore
(抑制異常)
實(shí)例:
import pandas as pd
data = pd.DataFrame({"A": ['1.1', '2.2', '3'], "B": ['4', '5', '6']}, dtype='float')
print(data.dtypes)
print(data['A'].astype(dtype='int'))
輸出:
A float64
B float64
dtype: object
0 1
1 2
2 3
Name: A, dtype: int32
0.4.3 to_numeric()
astype()
方法存在局限性坷备,通過(guò)to_numeric()
函數(shù)可以將傳入?yún)?shù)轉(zhuǎn)換為數(shù)值類(lèi)型熄浓。
語(yǔ)法:
pandas.to_numeric(arg,error='raise',downcast=None)
-
arg
:表示要轉(zhuǎn)換的數(shù)據(jù),可以是list
,tuple
,Series
-
errors
:錯(cuò)誤采取的處理方式
to_numeric
函數(shù)無(wú)法直接操作DataFrame
對(duì)象
實(shí)例:
import pandas as pd
data = pd.Series(['1', '1.2', '3'])
print(pd.to_numeric(data).dtypes)
輸出:
float64
1. 數(shù)據(jù)合并
1.1 軸向堆疊數(shù)據(jù)
通過(guò)使用concat()
函數(shù)可以沿著一條軸對(duì)多個(gè)對(duì)象進(jìn)行堆疊省撑,語(yǔ)法格式為:
pandas.concat(objs,axis=0,join='outer',join_axes=None,ignore_index=False,keys=None,levels=None,names=None,verify_integrity=False,sort=None,copy=True)
-
axis
:表示連接的軸向赌蔑,默認(rèn)為0,還可以設(shè)置為1 -
join
:表示連接方式竟秫,inner
表示內(nèi)連接娃惯,outer
表示外連接,默認(rèn)外連接 -
ignore_index
:接收布爾值肥败,默認(rèn)為False
趾浅,如果設(shè)置為True
,則表示清除現(xiàn)有索引并重置索引值 -
keys
:接收序列馒稍,表示添加最外層索引 -
levels
:用于構(gòu)建MultiIndex
的特定級(jí)別(唯一) -
names
:在設(shè)置了keys
和level
參數(shù)后皿哨,用于創(chuàng)建分層級(jí)別的名稱(chēng) -
verify_integerity
:檢查新的連接軸是否包含重復(fù)值。接收布爾值筷黔,當(dāng)設(shè)置為True
時(shí)往史,如果有重復(fù)的軸將會(huì)拋出錯(cuò)誤,默認(rèn)為False
1.1.1 橫向堆疊佛舱、縱向堆疊、內(nèi)連接挨决、外連接
橫向堆疊以行
為標(biāo)準(zhǔn)请祖,相同名稱(chēng)的行保存為一行,而縱向堆疊以列
為標(biāo)準(zhǔn)脖祈,相同名稱(chēng)的列保存為一列肆捕;內(nèi)連接是將兩個(gè)DataFrame
對(duì)象中都有的列或行進(jìn)行堆疊連接,而外連接是將兩個(gè)DataFrame
對(duì)象所有的列和行進(jìn)行堆疊連接盖高。
橫向堆疊默認(rèn)不考慮列索引而縱向堆疊默認(rèn)不考慮行索引慎陵,缺失值使用
NaN
填充
實(shí)例:
import pandas as pd
data1 = pd.DataFrame(
{
"A": [0, 1, 2, 3],
"B": [4, 5, 6, 7],
"C": [8, 9, 10, 11]
}, dtype=int)
data2 = pd.DataFrame({
"B": [12, 13, 14],
"C": [15, 16, 17],
"D": [18, 19, 20]
},
dtype=int)
# 縱向外連接
data3 = pd.concat([data1, data2], join='outer', axis=0)
print(data3)
輸出:
A B C D
0 0.0 4 8 NaN
1 1.0 5 9 NaN
2 2.0 6 10 NaN
3 3.0 7 11 NaN
0 NaN 12 15 18.0
1 NaN 13 16 19.0
2 NaN 14 17 20.0
1.2 主鍵合并數(shù)據(jù)
主鍵合并類(lèi)似于關(guān)系型數(shù)據(jù)庫(kù)眼虱,根據(jù)一個(gè)或多個(gè)鍵將不同的DataFrame
對(duì)象連接起來(lái),大多數(shù)是將兩個(gè)DataFrame
對(duì)象中重疊的列作為合并的鍵席纽,Pandas中提供了用于主鍵合并的merge()
函數(shù)捏悬,語(yǔ)法為:
pandas.merge(left,right,how='inner',on=None,left_on=None,right_on=None,left_index=False,right_index=False,sort=False,suffixes=('_x','_y'),copy=True,indicator=False,validate=None)
-
left
:參與合并的左側(cè)DataFrame
對(duì)象 -
right
:參與合并的右側(cè)DataFrame
對(duì)象 -
how
:表示連接方式,默認(rèn)為inner
润梯,該參數(shù)還支持如下取值:-
left
:使用左側(cè)的DataFrame
的鍵过牙,類(lèi)似SQL的左外連接 -
right
:使用右側(cè)的DataFrame
的鍵,類(lèi)似SQL的右外連接 -
outer
:使用兩個(gè)DataFrame
所有的鍵纺铭,類(lèi)似于SQL全連接 -
inner
:使用兩個(gè)DataFrame
鍵的交集寇钉,類(lèi)似于SQL內(nèi)連接
-
-
on
:用于連接的列名,必須存在于兩個(gè)DataFrame
對(duì)象中 -
left_on
:以左側(cè)DataFrame
作為連接鍵 -
right_on
:以右側(cè)DataFrame
作為連接鍵 -
left_index
:左側(cè)的行索引用作連接鍵 -
right_index
:右側(cè)的行索引用作連接鍵 -
sort
:是否排序舶赔,接收布爾值扫倡,默認(rèn)為False
-
suffixes
:用于追加到重疊列名的末尾,默認(rèn)為(_x,_y)
在使用
merge()
函數(shù)進(jìn)行合并時(shí)默認(rèn)使用重疊的列索引作為合并鍵竟纳,并采用內(nèi)連接的方式合并數(shù)據(jù)镊辕。
1.2.1 通過(guò)主鍵合并
針對(duì)同一個(gè)主鍵存在兩張不同字段的表,根據(jù)主鍵整合到一張表里面蚁袭,例如上圖中左側(cè)兩張表均有索引為key
的一列數(shù)據(jù)征懈,兩表通過(guò)key
列合并為一個(gè)表。即:
import pandas as pd
top = pd.DataFrame({"key": ['k0', 'k3', 'k4'], "A": [1, 3, 5], "B": [2, 4, 6]})
bottom = pd.DataFrame({
"key": ['k0', 'k2', 'k3'],
"C": [7, 9, 11],
"D": [8, 10, 12]
})
print(pd.merge(top, bottom, on="key"))
輸出:
key A B C D
0 k0 1 2 7 8
1 k3 3 4 11 12
1.2.2 多個(gè)主鍵合并
通過(guò)merge()
函數(shù)可以對(duì)含有多個(gè)重疊列的DataFrame
對(duì)象進(jìn)行合并揩悄,例如上圖中使用key
和B
作為合并鍵得到右側(cè)合并結(jié)果:
import pandas as pd
top = pd.DataFrame({"key": ['k0', 'k3', 'k4'], "A": [1, 3, 5], "B": [2, 4, 6]})
bottom = pd.DataFrame({
"key": ['k0', 'k2', 'k3'],
"C": [7, 9, 11],
"D": [8, 10, 12],
"B": [2, 3, 1]
})
print(pd.merge(top, bottom, on=["key", "B"]))
輸出為:
key A B C D
0 k0 1 2 7 8
merge()
函數(shù)支持四種合并方式分別為內(nèi)連接(inner)
卖哎、外連接(outer)
、左連接(left)
删性、右連接(right)
亏娜。函數(shù)中的how
默認(rèn)參數(shù)為inner
,不同合并方式解釋如下蹬挺。(下列操作均針對(duì)于key
為鍵值)
-
內(nèi)連接(inner)
:匹配兩個(gè)DataFrame
對(duì)象中均有的鍵值并合并 -
外連接(outer)
:合并兩個(gè)DataFrame
對(duì)象中所有的鍵值维贺,缺失值用NaN
填充 -
左連接(left)
:以merge
函數(shù)中第一個(gè)出現(xiàn)的DataFrame
對(duì)象的指定鍵值為標(biāo)準(zhǔn)進(jìn)行連接,第一個(gè)出現(xiàn)的DataFrame
表中數(shù)據(jù)將會(huì)全部顯示巴帮,而第二個(gè)出現(xiàn)的DataFrame
對(duì)象只會(huì)顯示與重疊數(shù)據(jù)行索引相同的數(shù)據(jù)溯泣,合并后缺失數(shù)據(jù)用NaN
填充 -
右連接(right)
:以merge
函數(shù)中第二個(gè)出現(xiàn)的DataFrame
對(duì)象的指定鍵值為標(biāo)準(zhǔn)進(jìn)行連接,第二個(gè)出現(xiàn)的DataFrame
表中數(shù)據(jù)將會(huì)全部顯示榕茧,而第一個(gè)出現(xiàn)的DataFrame
對(duì)象只會(huì)顯示與重疊數(shù)據(jù)行索引相同的數(shù)據(jù)垃沦,合并后缺失數(shù)據(jù)用NaN
填充
示例代碼:
import pandas as pd
left = pd.DataFrame({
'key': ['K0', 'K1', 'K2'],
'A': ['A0', 'A1', 'A2'],
'B': ['B0', 'B1', 'B2']
})
right = pd.DataFrame({
'key': ['K0', 'K1', 'K2', 'K3'],
'B': ['B0', 'B1', 'B2', 'B3'],
'C': ['C0', 'C1', 'C2', 'C3'],
'D': ['D0', 'D1', 'D2', 'D3']
})
# 左連接
data_left = pd.merge(left, right, how='left', on='key')
# 右連接
data_right = pd.merge(left, right, how='right', on='key')
# 內(nèi)連接
data_inner = pd.merge(left, right, how='inner', on='key')
# 外連接
data_outer = pd.merge(left, right, how='outer', on='key')
如果兩張表行索引和列索引均沒(méi)有重疊部分,可以通過(guò)將merge()
函數(shù)的left_index
與right_index
均設(shè)置為True
即可用押,例如:
import pandas as pd
left = pd.DataFrame({'A': ['A0', 'A1'], 'B': ['B0', 'B1']}, index=['a', 'b'])
right = pd.DataFrame({'C': ['C0', 'C1'], 'D': ['D0', 'D1']})
data = pd.merge(left, right, how='outer', left_index=True, right_index=True)
print(data)
輸出為:
A B C D
a A0 B0 NaN NaN
b A1 B1 NaN NaN
0 NaN NaN C0 D0
1 NaN NaN C1 D1
1.3 根據(jù)行索引合并數(shù)據(jù)
1.3.1 join()
方法
join()
方法能夠通過(guò)索引或者指定的列來(lái)連接DataFrame
肢簿。
語(yǔ)法:
join(other,on=None,how='left',lsuffix='',rsuffix='',sort=False)
-
on
:用于連接的列名 -
lsuffix
:接收字符串,用于在左側(cè)重疊的列名后添加后綴 -
rsuffix
:接收字符串,用于在右側(cè)重疊的列名后添加后綴 -
sort
:接收布爾值池充,根據(jù)連接鍵對(duì)合并的數(shù)據(jù)進(jìn)行排序桩引,默認(rèn)為False
實(shí)例:
import pandas as pd
left = pd.DataFrame({'A': ['A0', 'A1'], 'B': ['B0', 'B1']}, index=['a', 'b'])
right = pd.DataFrame({'C': ['C0', 'C1'], 'D': ['D0', 'D1']})
data = left.join(right, how="outer")
print(data)
輸出:
A B C D
a A0 B0 NaN NaN
b A1 B1 NaN NaN
0 NaN NaN C0 D0
1 NaN NaN C1 D1
1.4 合并重疊數(shù)據(jù)
在處理數(shù)據(jù)時(shí),當(dāng)一個(gè)DataFrame
對(duì)象出現(xiàn)了缺失值收夸,對(duì)于這些缺失數(shù)據(jù)如果想要通過(guò)其他的DataFrame
對(duì)象中的數(shù)據(jù)填充坑匠,可以通過(guò)combine_first()
方法填充缺失數(shù)據(jù)。
語(yǔ)法:
combine_first(other)
-
other
:用于接收填充缺失值的對(duì)象
實(shí)例:
import pandas as pd
from numpy import NaN
left = pd.DataFrame({
'key': ['K0', 'K1', 'K2', 'K3'],
'A': ['A0', NaN, 'A2', 'A3'],
'B': [NaN, 'B1', NaN, 'B3']
})
right = pd.DataFrame({
'A': ['C0', 'C1', 'C2'],
'B': ['D0', 'D1', 'D2']
},
index=[1, 2, 0])
print(left.combine_first(right))
輸出:
A B key
0 A0 D2 K0
1 C0 B1 K1
2 A2 D1 K2
3 A3 B3 K3
使用
combine_first
方法合并兩個(gè)DataFrame
對(duì)象時(shí)咱圆,必須確保他們的行索引和列索引有重疊部分
2. 數(shù)據(jù)重塑
在Pandas
中大多數(shù)情況DataFrame
對(duì)象更便于操作笛辟,因?yàn)?code>DataFrame對(duì)象很容易獲取每行或每列的數(shù)據(jù)。但是有時(shí)候需要將DataFrame
對(duì)象轉(zhuǎn)換為Series
對(duì)象序苏,因此需要對(duì)數(shù)據(jù)進(jìn)行重塑手幢。
2.1 重塑層次化索引
重塑層次化索引的操作主要是stack()
方法和unstack()
方法,前者是將數(shù)據(jù)的列旋轉(zhuǎn)為行忱详,后者是將數(shù)據(jù)的行旋轉(zhuǎn)成列围来。
2.1.1 stack()
方法
語(yǔ)法:
DataFrame.stack(level=-1,dropna=True)
-
level
:表示操作的內(nèi)層索引,若設(shè)置為0匈睁,表示操作外層索引监透,默認(rèn)為-1 -
dropna
:表示是否將旋轉(zhuǎn)后的缺失值刪除,默認(rèn)為True
(過(guò)濾缺失值)
實(shí)例:
import pandas as pd
data = pd.DataFrame({"A": ['A0', 'A1', 'A2'], "B": ['B0', 'B1', 'B2']})
result = data.stack()
print(result)
輸出:
0 A A0
B B0
1 A A1
B B1
2 A A2
B B2
通過(guò):
print(type(result))
可查看結(jié)果為:
<class 'pandas.core.series.Series'>
2.1.2 unstack
方法
語(yǔ)法:
DataFrame.unstack(level=-1,fill_value=None)
-
fill_value
:若產(chǎn)生了缺失值航唆,則可以設(shè)置這個(gè)參數(shù)用來(lái)替換NaN
實(shí)例:
將上例中還原:
print(result.unstack())
輸出:
A B
0 A0 B0
1 A1 B1
2 A2 B2
可以使用stack
對(duì)多層索引進(jìn)行重塑胀蛮。
import pandas as pd
import numpy as np
data = pd.DataFrame(np.array([[26, 20, 22, 26], [30, 25, 24, 20]]),
index=['男生人數(shù)', '女生人數(shù)'],
columns=[['一樓', '一樓', '二樓', '二樓'],
['A教室', 'B教室', 'A教室', 'B教室']])
result = data.stack()
print(result)
輸出:
一樓 二樓
男生人數(shù) A教室 26 22
B教室 20 26
女生人數(shù) A教室 30 24
B教室 25 20
2.2 軸向旋轉(zhuǎn)
2.2.1 pivot
方法
pivot
方法提供的功能是根據(jù)給定行索引或列索引重新組織一個(gè)DataFrame
對(duì)象。
語(yǔ)法:
DataFrame.pivot(index=None,columns=None,values=None)
-
index
:用于創(chuàng)建新DataFrame
對(duì)象的行索引糯钙,如果未設(shè)置粪狼,則使用原DataFrame
對(duì)象的索引。 -
columns
:列索引 -
values
:值
實(shí)例:
出售日期 | 商品名稱(chēng) | 價(jià)格(元) |
---|---|---|
2017年5月25日 | 榮耀9青春版 | 999 |
2017年5月25日 | 小米6x | 1399 |
2017年5月25日 | OPPO A1 | 1399 |
2017年6月18日 | 榮耀9青春版 | 800 |
2017年6月18日 | 小米6x | 1200 |
2017年6月18日 | OPPO A1 | 1250 |
將上述表格轉(zhuǎn)化為下表:
商品名稱(chēng)/出售日期 | 榮耀9青春版 | 小米6x | OPPO A1 |
---|---|---|---|
2017年5月25日 | 999 | 1399 | 1399 |
2017年6月18日 | 800 | 1200 | 1250 |
import pandas as pd
data = pd.read_excel('./ProductInfo.xlsx')
result = data.pivot(index="出售日期", columns="商品名稱(chēng)", values="價(jià)格(元)")
print(result)
3. 數(shù)據(jù)轉(zhuǎn)換
當(dāng)數(shù)據(jù)進(jìn)行清洗之后任岸,需要對(duì)數(shù)據(jù)進(jìn)行一些合理的轉(zhuǎn)換再榄,使這些數(shù)據(jù)更符合分析的要求。
3.1 重命名軸索引
重命名軸索引是數(shù)據(jù)分析中比較常見(jiàn)的操作享潜,可以通過(guò)rename()
方法重命名個(gè)別列索引或行索引的標(biāo)簽或名稱(chēng)困鸥。
3.1.1 語(yǔ)法格式:
rename(mapper=None,index=None,columns=None,axis=None,copy=True,inplace=False,level=None)
-
index,columns
:表示待轉(zhuǎn)換的行索引和列索引 -
axis
:表示軸的名稱(chēng),可以使用index
或columns
剑按,也可以使用數(shù)字0或1 -
copy
:表示是否復(fù)制底層的數(shù)據(jù)疾就,默認(rèn)為False
-
inplace
:默認(rèn)為False
,表示是否返回新的Pandas
對(duì)象吕座,如果設(shè)置為True
虐译,則會(huì)忽略復(fù)制的值 -
level
:表示級(jí)別的名稱(chēng),默認(rèn)為None
吴趴。對(duì)于多級(jí)索引,只重命名指定的標(biāo)簽。
3.1.2 實(shí)例
將下列表格列索引更改為
a
,b
,c
A | B | C | |
---|---|---|---|
0 | 1 | 2 | 3 |
1 | 4 | 5 | 6 |
2 | 7 | 8 | 9 |
3 | 10 | 11 | 12 |
import pandas as pd
data = pd.DataFrame({
"A": [1, 4, 7, 10],
"B": [2, 5, 8, 11],
"C": [3, 6, 9, 12]
})
result = data.rename(str.lower, axis="columns")
print(result)
3.1.3 輸出
a b c
0 1 2 3
1 4 5 6
2 7 8 9
3 10 11 12
3.1.4 其他說(shuō)明
使用rename()
方法也可以對(duì)行索引進(jìn)行重命名:
result_s = result.rename(index={1: 'a', 2: 'b'})
print(result_s)
輸出:
a b c
0 1 2 3
a 4 5 6
b 7 8 9
3 10 11 12
3.2 離散化連續(xù)數(shù)據(jù)
有時(shí)候我們需要將數(shù)據(jù)進(jìn)行離散化锣枝,可以使用cut()
函數(shù)厢拭。
3.2.1 函數(shù)語(yǔ)法:
pandas.cut(x,bins,right=True,labels=None,retbins=False,precision=3,include_lowest=False,duplicates='raise')
-
x
:表示要分箱的數(shù)組,必須是一維的 -
bins
:接收int和序列類(lèi)型的數(shù)據(jù) -
right
:是否包含右端點(diǎn)撇叁,默認(rèn)包含 -
labels
:用于生成區(qū)間的標(biāo)簽 -
retbins
:是否返回bin -
precision
:精度供鸠,默認(rèn)保留三位小數(shù) -
include_lowest
:是否包含左端點(diǎn)
3.2.2 實(shí)例
import pandas as pd
ages = [20, 22, 25, 27, 21, 23, 37, 31, 61, 45, 32]
bins = [0, 18, 25, 35, 60, 100]
cuts = pd.cut(ages, bins)
print(cuts)
3.2.3 輸出
[(18, 25], (18, 25], (18, 25], (25, 35], (18, 25], ..., (35, 60], (25, 35], (60, 100], (35, 60], (25, 35]]
Length: 11
Categories (5, interval[int64]): [(0, 18] < (18, 25] < (25, 35] < (35, 60] < (60, 100]]
3.3 啞變量處理類(lèi)別型數(shù)據(jù)
在Pandas中,可以使用get_dummies()
函數(shù)對(duì)類(lèi)別特征進(jìn)行啞變量處理陨闹。語(yǔ)法如下:
pandas.get_dummies(data,prefix=None,prefix_sep='_',dummy_na=False,columns=None,sparse=False,drop_first=False,dtype=None)
-
data
:可接收數(shù)組楞捂,DataFrame
或Serise
對(duì)象,表示啞變量處理的數(shù)據(jù) -
prefix
:表示列名的前綴趋厉,默認(rèn)為None -
prefix_sep
:用于附加前綴作為分隔符寨闹,默認(rèn)為_
-
dummy_na
:表示是否為NaN值添加一列,默認(rèn)為False -
sparse
:表示虛擬列是否是稀疏的君账,默認(rèn)為False -
drop_first
:是否通過(guò)從k個(gè)分類(lèi)級(jí)別中刪除第一個(gè)級(jí)來(lái)獲得k-1個(gè)分類(lèi)級(jí)別繁堡,默認(rèn)為False
例如:
import pandas as pd
data = pd.DataFrame({"職業(yè)": ["工人", "學(xué)生", "司機(jī)", "教師", "導(dǎo)游"]})
print(pd.get_dummies(data, prefix=['col_']))
輸出為:
col__司機(jī) col__學(xué)生 col__導(dǎo)游 col__工人 col__教師
0 0 0 0 1 0
1 0 1 0 0 0
2 1 0 0 0 0
3 0 0 0 0 1
4 0 0 1 0 0