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