Pandas是一個強大的分析結構化數據的工具集,主要用於數據挖掘和數據分析,同時也提供數據清洗功能。
很多初學者在數據的選取,修改和切片時經常面臨一些困惑。這是因為Pandas提供了太多方法可以做同樣的事情,方法選擇不當,可能導致一些意想不到的錯誤。
Pandas切片
Pandas數據訪問方式包括:df[] ,.at,.iat,.loc,.iloc(之前有ix方法,pandas1.0之后已被移除)
- df[] :直接索引
- at/iat:通過標簽或行號獲取某個數值的具體位置。
- loc:通過標簽選取數據,即通過index和columns的值進行選取。loc方法有兩個參數,按順序控制行列選取,范圍包括start和end。
- iloc:通過行號選取數據,即通過數據所在的自然行列數為選取數據。iloc方法也有兩個參數,按順序控制行列選取。
它們之間的區別不是文本重點,大家可以新建一個dataframe練習一下,本文我們主要來一個錯誤示范,然后給大家提一些合理的建議。
錯誤示范
新建一個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
假設我們要查找與“x”列對應的所有DataFrame元素都大於3,並根據此更改將所有對應的“ y”值更改為50。
我們來先試一個看起來毫無問題的方法
df[df['x']>3]['y']=50
運行之后,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
根據提示信息,我們使用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
得到預期結果√
這是為什么呢?這里我們就遇到了所謂的“鏈接索引”,具體原因是使用了兩個索引器,例如: df[][]
df[df['x']>3] 導致Pandas創建原始DataFrame的單獨副本
df[df['x']>3]['y'] = 50 將新值分配給“ y”列,但在此臨時創建的副本上,而不是原始DataFrame上。
反轉切片的順序時,即先調用列,然后再調用我們要滿足的條件,便得到了預期的結果:
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
但是同樣會給出一個Warning:
A value is trying to be set on a copy of a slice from a DataFrame
SettingWithCopyWarning 是一個警告 Warning,而不是錯誤 Error。
這是因為,當我們從DataFrame中僅選擇一列時,Pandas會創建一個視圖,而不是副本。關於視圖和副本的區別,下圖最為形象:
df[]方法會創建視圖
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
當我們創建了視圖后,pandas就會出現warning,因為它不知道我們是否只想更改y系列(通過z)或原始值df。
如果我們要提取“z”作為獨立對象怎么辦?pandas提供了copy()方法,當我們將命令更新為以下所示的命令時:
z = df['y'].copy()
我們將在內存中創建一個具有其自己地址的全新對象,並且對“z”進行的任何更新df都將不受影響。
實際上有兩個要點,可以使我們在使用切片和數據操作時免受任何有害影響:
- 避免鏈接索引。始終選擇.loc/ .iloc(或.at/ .iat)方法;
- 使用copy() 創建獨立的對象,並保護原始資源免遭不當操縱。
參考
https://www.jianshu.com/p/199a653e9668
https://www.kdnuggets.com/2020/04/stop-hurting-pandas.html