Pandas切片操作:一個(gè)很容易忽視的錯(cuò)誤
Pandas是一個(gè)強(qiáng)大的分析結(jié)構(gòu)化數(shù)據(jù)的工具集,主要用于數(shù)據(jù)挖掘和數(shù)據(jù)分析,同時(shí)也提供數(shù)據(jù)清洗功能。
很多初學(xué)者在數(shù)據(jù)的選取,修改和切片時(shí)經(jīng)常面臨一些困惑。這是因?yàn)镻andas提供了太多方法可以做同樣的事情,方法選擇不當(dāng),可能導(dǎo)致一些意想不到的錯(cuò)誤。
Pandas切片
Pandas數(shù)據(jù)訪問方式包括:df[] ,.at,.iat,.loc,.iloc(之前有ix方法,pandas1.0之后已被移除)
df[] :直接索引 at/iat:通過標(biāo)簽或行號(hào)獲取某個(gè)數(shù)值的具體位置。 loc:通過標(biāo)簽選取數(shù)據(jù),即通過index和columns的值進(jìn)行選取。loc方法有兩個(gè)參數(shù),按順序控制行列選取,范圍包括start和end。 iloc:通過行號(hào)選取數(shù)據(jù),即通過數(shù)據(jù)所在的自然行列數(shù)為選取數(shù)據(jù)。iloc方法也有兩個(gè)參數(shù),按順序控制行列選取。
它們之間的區(qū)別不是文本重點(diǎn),大家可以新建一個(gè)dataframe練習(xí)一下,本文我們主要來一個(gè)錯(cuò)誤示范,然后給大家提一些合理的建議。
錯(cuò)誤示范
新建一個(gè)DataFrame
df = pd.DataFrame(
{'x':[1,5,4,3,4,5],
'y':[.1,.5,.4,.3,.4,.5],
'w':[11,15,14,13,14,15]})
x y w
0 1 0.1 11
1 5 0.5 15
2 4 0.4 14
3 3 0.3 13
4 4 0.4 14
5 5 0.5 15
假設(shè)我們要查找與“x”列對(duì)應(yīng)的所有DataFrame元素都大于3,并根據(jù)此更改將所有對(duì)應(yīng)的“ y”值更改為50。
我們來先試一個(gè)看起來毫無問題的方法
df[df['x']>3]['y']=50
運(yùn)行之后,df沒有任何變化,Warning如下:
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead
根據(jù)提示信息,我們使用loc方法
df.loc[df['x']>3,'y']=50
x y w
0 1 0.1 11
1 5 50.0 15
2 4 50.0 14
3 3 0.3 13
4 4 50.0 14
5 5 50.0 15
得到預(yù)期結(jié)果√?
這是為什么呢?這里我們就遇到了所謂的“鏈接索引”,具體原因是使用了兩個(gè)索引器,例如:df[][]
df[df['x']>3] 導(dǎo)致Pandas創(chuàng)建原始DataFrame的單獨(dú)副本
df[df['x']>3]['y'] = 50 將新值分配給“ y”列,但在此臨時(shí)創(chuàng)建的副本上,而不是原始DataFrame上。
反轉(zhuǎn)切片的順序時(shí),即先調(diào)用列,然后再調(diào)用我們要滿足的條件,便得到了預(yù)期的結(jié)果:
df['y'][df['x']>3]=50
x y w
0 1 0.1 11
1 5 50.0 15
2 4 50.0 14
3 3 0.3 13
4 4 50.0 14
5 5 50.0 15
df[]方法會(huì)創(chuàng)建視圖df
x y w
0 1 0.1 11
1 5 0.5 15
2 4 0.4 14
3 3 0.3 13
4 4 0.4 14
5 5 0.5 15
z = df['y'] # view of column 'y'
z[z>=0.5] = 30
z
0 0.1
1 30.0
2 0.4
3 0.3
4 0.4
5 30.0
df
x y w
0 1 0.1 11
1 5 30.0 15
2 4 0.4 14
3 3 0.3 13
4 4 0.4 14
5 5 30.0 15
當(dāng)我們創(chuàng)建了視圖后,pandas就會(huì)出現(xiàn)warning,因?yàn)樗恢牢覀兪欠裰幌敫膟系列(通過z)或原始值df。如果我們要提取“z”作為獨(dú)立對(duì)象怎么辦?pandas提供了copy()方法,當(dāng)我們將命令更新為以下所示的命令時(shí):
z = df['y'].copy()
我們將在內(nèi)存中創(chuàng)建一個(gè)具有其自己地址的全新對(duì)象,并且對(duì)“z”進(jìn)行的任何更新df都將不受影響。實(shí)際上有兩個(gè)要點(diǎn),可以使我們?cè)谑褂们衅蛿?shù)據(jù)操作時(shí)免受任何有害影響:
避免鏈接索引,始終選擇.loc/ .iloc(或.at/ .iat)方法; 使用copy() 創(chuàng)建獨(dú)立的對(duì)象,并保護(hù)原始資源免遭不當(dāng)操縱
參考
https://www.jianshu.com/p/199a653e9668 https://www.kdnuggets.com/2020/04/stop-hurting-pandas.html
python爬蟲人工智能大數(shù)據(jù)公眾號(hào)

