今天是pandas數據處理專題第三篇文章,我們來聊聊DataFrame中的索引。
上篇文章當中我們簡單介紹了一下DataFrame這個數據結構的一些常見的用法,從整體上大概了解了一下這個數據結構。今天這一篇我們將會深入其中索引相關的應用方法,了解一下DataFrame的索引機制和使用方法。
數據准備
上一篇文章當中我們了解了DataFrame可以看成是一系列Series組合的dict,所以我們想要查詢表中的某一列,也就是查詢某一個Series,我們只需要像是dict一樣傳入key值就可以查找了。但是,如果我們想要查找某一行應該怎么辦?難道手動去遍歷每一列么?這顯然是不現實的。
所以DataFrame當中也為我們封裝了現成的行索引的方法,行索引的方法一共有兩個,分別是loc,iloc。這兩種方法都可以查詢某一行,只是查詢的參數不同,本質上沒有高下之分,大家可以自由選擇。
首先,我們還是用上次的方法來創建一個DataFrame用來測試:
data = {'name': ['Bob', 'Alice', 'Cindy', 'Justin', 'Jack'], 'score': [199, 299, 322, 212, 311], 'gender': ['M', 'F', 'F', 'M', 'M']}
df = pd.DataFrame(data)
loc
首先我們來介紹loc,loc方法可以根據傳入的行索引查找對應的行數據。注意,這里說的是行索引,而不是行號,它們之間是有區分的。行索引其實對應於Series當中的Index,也就是對應Series中的索引。所以我們一般把行索引稱為Index,而把列索引稱為columns。
我們在之前的文章當中了解過,對於Series來說,它的Index可以不必是整數,也可以擁有重復元素。當然如果我們不指定的話,它會和行號一樣,都是整數:
我們可以手動修改df的index,來看看當行索引不是整數的時候,是不是也一樣生效。
可以明顯看出來是生效的,而且我們也可以傳入一個索引數組來查詢多行。
不僅如此,loc方法也是支持切片的,也就是說雖然我們傳進的是一個字符串,但是它在原數據當中是對應了一個位置的。我們使用切片,pandas會自動替我們完成索引對應位置的映射。
但是索引對應的切片出來的結果是閉區間,這一點和Python通常的切片用法不同,需要當心。
另外,loc是支持二維索引的,也就是說我們不但可以指定行索引,還可以在此基礎上指定列。說白了我們可以選擇我們想要的行中的字段。
列索引也可以切片,並且可以組合在一起切片:
iloc
iloc從名字上來看就知道用法應該和loc不會差太大,實際上也的確如此。iloc的用法幾乎和loc完全一樣,唯一不同的是,iloc接收的不是index索引而是行號。我們可以通過行號來查找我們想要的行,既然是行號,也就說明了固定死了我們傳入的參數必須是整數。
同樣iloc也支持傳入多個行號。
iloc也支持二維索引,但是對於列,我們也必須傳入整數,也就是這個列對應的列號。
和loc不同,iloc的切片也是左閉右開。
我們在使用當中往往會覺得不方便,因為我們往往是知道我們需要的行號和列名。也就是知道一個索引知道一個位置,而不是兩個位置或者是兩個索引,所以使用loc也不方便使用iloc也不方便。這個時候可以取巧,我們可以通過iloc找出對應的行之后,再通過列索引的方式去查詢列。
這里我們在iloc之后又加了一個方括號,這其實不是固定的用法,而是兩個語句。先是iloc查詢行之后,再對這些行組成的新的DataFrame進行列索引。
但如果是通過索引來查找對應的若干行的話,其實也可以不用使用iloc,我們可以直接在df后面加上方括號來查詢,一樣可以得到結果。
但是這種方式有一個限制,就是后面只能傳入一個切片,而不能是一個整數。比如我想要單獨查詢第2行,我們通過df[2]來查詢是會報錯的。因為pandas會混淆不知道二手手機地圖我們究竟是想要查詢一列還是一行,所以這個時候只能通過iloc或者是loc進行。
邏輯表達式
和numpy一樣,DataFrame也支持傳入一個邏輯表達式作為查詢條件。
比如我們想要查詢分數大於200的行,可以直接在方框中寫入查詢條件df['score'] > 200。
實際上我們知道df['score']可以獲得這一列對應的Series,加上了判斷之后,得到的結果應該是一個Bool型的Series。所以如果我們直接傳入一個bool型的數組也是一樣可以完成查詢的:
如果表達式有多個也沒問題,不過需要使用括號將表達式包起來,並且多個表達式之間用位運算符連接,比如&, |。
總結
今天主要介紹了loc、iloc和邏輯索引在pandas當中的用法,這也是pandas數據查詢最常用的方法,也是我們使用過程當中必然會用到的內容。建議大家都能深刻理解,把它記牢。
很多人在學習pandas的前期遇到最多的一個問題就是會把iloc和loc記混淆,搞不清楚哪個是索引查詢哪個是行號查詢。曾經原本還有一個ix方法,可以兼顧iloc和loc的功能,既可以索引查詢也可以行號查詢。但是可惜的是,在pandas最新的版本當中這個方法已經被廢棄了。我個人也沒有什么太好的辦法,只能熟能生巧了,多用幾次就記住了。