當我們學習 Pandas 時,大家都試圖弄清楚的一件煩人的事情就是 .loc
和 .iloc
之間的區別。
讓我們結束這種困惑,澄清這兩個方法之間的差異。我會提供很多例子,希望到這篇博客結尾時,這個區別會變得更加清晰。
在 Pandas 中,.loc 和 .iloc 是什麼?
.loc
和 .iloc
都是 Pandas DataFrame 的重要屬性,並且都用於選擇特定的數據子集。它們的目的是訪問並使能夠操控 DataFrame 的特定部分,而不是整個 DataFrame。
特徵 |
.loc |
.iloc |
語法 |
df.loc[row_indexer, column_indexer] |
df.iloc[row_indexer, column_indexer] |
索引方法 |
基於標籤的索引 |
基於位置的索引 |
用於參考 |
行和列標籤(名稱) |
行和列的數字索引(從0開始) |
正如我們從表中看到的,語法看起來非常相似。不同之處在於我們如何使用row_indexer
和column_indexer
參數。這是因為這兩種方法提供了不同的數據索引方法:.loc
基於標籤名稱進行索引,而.iloc
則以行和列的數字位置索引作為參數。
讓我們詳細檢查這兩種方法,首先從.loc
開始。
使用 .loc:按標籤選擇
為了說明這些概念,讓我們考慮一個假設的客戶數據庫,這個數據庫由名為 df
的 DataFrame 表示,其中 Customer ID
代表行索引 i:
客戶編號 |
姓名 |
國家 |
地區 |
年齡 |
C123 |
約翰·杜 |
美國 |
北美洲 |
67 |
C234 |
佩特拉·穆勒 |
德國 |
歐洲 |
51 |
C345 |
Ali Khan |
Pakistan |
Asia |
19 |
C456 |
Maria Gonzalez |
Mexico |
North America |
26 |
C567 |
David Lee |
China |
Asia |
40 |
有四種使用.loc
來選擇行的主要方法,包括:
- 選擇單行
- 選擇多行
- 選擇一組連續的行
- 條件行選擇
使用.loc選擇單行
要選擇單行,我們使用要檢索的行標籤作為row_indexer
。因此,語法如下:df.loc['row_label']
。讓我們使用這個方法顯示我們的客戶Ali Khan的所有信息:
df.loc['C345']
C345 |
|
名稱 |
Ali Khan |
國家 |
巴基斯坦 |
地區 |
亞洲 |
年齡 |
19 |
使用 .loc 選擇多行
如果我們想選擇不一定是連續的多行,我們必須將它們的行標籤列表作為 row_indexer
參數傳遞。這意味著我們需要使用兩對方括號:一個是常規的 .loc
語法,另一個是標籤列表。
這行 df.loc[['row_label_1', 'row_label_2']]
將返回列表中指定的 df
數據框的兩行。假設我們想知道不僅是 Ali Khan 的信息,還有 David Lee 的信息:
df.loc[['C345', 'C567']]
客戶ID |
姓名 |
國家 |
地區 |
年齡 |
C345 |
阿里·汗 |
巴基斯坦 |
亞洲 |
19 |
C567 |
大衛·李 |
中國 |
亞洲 |
40 |
使用 .loc 選擇行的一部分
我們可以通過在中間加上冒號來傳遞第一行和最後一行的標籤來選擇行範圍: df.loc['row_label_start':'row_label_end']
。我們可以這樣顯示我們的數據框的前四行:
df.loc['C123' : 'C456']
客戶ID |
姓名 |
國家 |
地區 |
註冊日期 |
C123 |
約翰·多 |
美國 |
北美洲 |
67 |
C234 |
佩特拉·穆勒 |
德國 |
歐洲 |
51 |
C345 |
阿里·汗 |
巴基斯坦 |
亞洲 |
19 |
C456 |
瑪麗亞·岡薩雷斯 |
墨西哥 |
北美洲 |
26 |
這裡有兩件事需要記住:
- 輸出包括在
row_label_end
中指定的行。這與稍後會介紹的.iloc
不同。 - 我們只使用一對方括號,即使我們想檢索多行。我們並不使用列表來指定各種行,因此使用兩對方括號會返回
SyntaxError
。
使用.loc的行條件選擇
我們也可以根據條件表達式來返回行。我們可以根據是否滿足某個條件過濾所有行,並僅顯示滿足條件的行。
相應的語法是df.loc[conditional_expression]
,其中conditional_expression
是有關特定列中允許值的陳述。
對於具有非數字數據的列(如姓名
或國家
),語句只能使用等於或不等於運算符,因為值之間沒有順序。例如,我們可以返回所有不來自亞洲的客戶的行:
df.loc[df['Region'] != 'Asia']
客戶編號 |
姓名 |
國家 |
地區 |
年齡 |
C123 |
約翰·杜 |
美國 |
北美洲 |
67 |
C234 |
佩特拉·穆勒 |
德國 |
歐洲 |
51 |
C456 |
瑪莉亞·岡薩雷斯 |
墨西哥 |
北美洲 |
26 |
使用 .loc 選擇單一列
要選擇列,我們需要指定 column_indexer
參數,該參數位於 row_indexer
參數之後。如果我們只想指定 column_indexer
,我們需要以某種方式標記我們希望返回所有行並僅對列進行過濾。讓我們看看如何做到這一點!
選擇單一列可以通過指定相應列的 column_indexer
來完成。要檢索所有行,我們需要用一個簡單的冒號指定 row_indexer
。我們得到的語法看起來像這樣: df.loc[:, 'column_name']
.
讓我們顯示每位客戶的 姓名
:
df.loc[:, 'Name']
客戶編號 |
姓名 |
C123 |
約翰·多 |
C234 |
Petra Müller |
C345 |
Ali Khan |
C456 |
Maria Gonzalez |
C567 |
David Lee |
Selecting multiple columns using .loc
Similar to selecting multiple rows, we need to pass a list of column labels if we want to return multiple columns of a DataFrame that do not necessarily follow each other in order: df.loc[:, [col_label_1, 'col_label_2']]
.
Assuming we wanted to add all customers’ Age
to our last output, it would work like this:
df.loc[:, ['Name', 'Age']]
Customer ID |
Name |
Age |
C123 |
John Doe |
67 |
C234 |
Petra Müller |
51 |
C345 |
阿里·汗 |
19 |
C456 |
瑪麗亞·岡薩雷斯 |
26 |
C567 |
大衛·李 |
40 |
使用 .loc 選取列的範圍
在兩個標籤之間使用冒號將選取這兩個指定列之間的所有列,範圍是包含結束列的,這意味著名為 col_end
的列也會在標準語法中被選取,語法如下:df.loc[:, 'col_start':'col_end']
。
如果我們對客戶的 姓名
、國家
和 地區
感興趣,我們的代碼行可以是:
df.loc[:, 'Name':'Region']
客戶ID |
姓名 |
國家 |
地區 |
C123 |
約翰·多 |
美國 |
北美洲 |
C234 |
Petra Müller |
德國 |
歐洲 |
C345 |
Ali Khan |
巴基斯坦 |
亞洲 |
C456 |
Maria Gonzalez |
墨西哥 |
北美洲 |
C567 |
David Lee |
中國 |
亞洲 |
使用.loc結合行和列的選擇
也可以指定row_indexer
和column_indexer
。這可用於檢索單個信息,即DataFrame中的一個單元格。為此,我們使用語法df.loc['row_label', 'column_name']
來指定一行和一列。
更有用的情況是返回一個專注於我們感興趣的行和列集的子DataFrame。可以使用方括號將兩個索引器都指定為列表,也可以使用冒號進行切片,甚至可以將其與行選擇的條件表達式結合使用。
以下是一個返回每位年齡超過30歲的客戶的Name
、Country
和Region
的示例:
df.loc[df['Age'] > 30, 'Name':'Region']
客戶編號 |
姓名 |
國家 |
地區 |
C123 |
約翰·多 |
美國 |
北美洲 |
C234 |
佩特拉·穆勒 |
德國 |
歐洲 |
C567 |
大衛·李 |
中國 |
亞洲 |
使用 .iloc:按整數位置選擇
.iloc
是按位置而不是標籤選擇的。使用 .iloc
的標準語法是:df.iloc[row_indexer, column_indexer]
。需要注意兩個特殊事項:
- 從 0 開始計數:第一行和第一列的索引為 0,第二行的索引為 1,以此類推。
- 範圍結束值的排他性:使用切片時,冒號後面指定的行或列不包含在選擇中。
使用 .iloc 選擇單行
單行可以使用表示行索引號的整數作為 row_indexer
來選擇。我們不需要引號,因為我們輸入的是整數而不是像使用 .loc
時的標籤字符串。要返回名為 df
的 DataFrame 的第一行,請輸入 df.iloc[0]
。
在我們的示例 DataFrame 中,這行代碼返回約翰·杜的信息:
df.iloc[0]
C123 |
|
Name |
John Doe |
Country |
United States |
Region |
North America |
Age |
67 |
在`.iloc`中選擇多行
在`.iloc`中選擇多行與`.loc`中的操作方式相同—我們將行索引整數放入帶有方括號的列表中。語法如下:df.iloc[[0, 3, 4]]
。
我們客戶表中的相應輸出如下:
df.iloc[[0, 3, 4]]
Customer ID |
Name |
Country |
Region |
Age |
C123 |
John Doe |
美國 |
北美洲 |
67 |
C456 |
瑪麗亞·冈萨雷斯 |
墨西哥 |
北美洲 |
26 |
C567 |
大衛·李 |
中國 |
亞洲 |
40 |
通過.iloc選擇行片段
要選擇一段行,我們在兩個指定的行索引整數之間使用冒號。現在,我們必須注意前面提到的排他性。
我們可以以df.iloc[1:4]
這行代碼作為例子來說明這個概念。索引號1表示第二行,因此我們的片段從那裡開始。索引整數4代表第五行 – 但由於.iloc
在選擇片段時不包含,我們的輸出將包括直到此行之前的所有行。因此,它將返回第二、第三和第四行。
讓我們證明這行代碼的工作原理:
df.iloc[1:4]
客戶編號 |
名稱 |
國家 |
地區 |
年齡 |
C234 |
Petra Müller |
德國 |
歐洲 |
51 |
C345 |
Ali Khan |
巴基斯坦 |
亞洲 |
19 |
C456 |
Maria Gonzalez |
墨西哥 |
北美洲 |
26 |
選擇使用.iloc選擇單列
使用 .iloc
選擇欄位的邏輯遵循我們到目前為止學到的內容。讓我們看看它如何運作於單一欄位、多個欄位和欄位切片。
就像使用 .loc
一樣,重要的是在我們能夠進入 column_indexer
之前,必須指定 row_indexer
。要檢索 df
的第三欄對於每一行的值,我們輸入 df.iloc[:, 2]
。
因為 Region
是我們資料框中的第三欄,這行代碼將會返回它的值:
df.iloc[:, 2]
客戶編號 |
區域 |
C123 |
北美洲 |
C234 |
歐洲 |
C345 |
亞洲 |
C456 |
北美洲 |
C567 |
亞洲 |
使用 .iloc 選擇多個列
要選擇不一定連續的多列,我們可以再次輸入包含整數的列表作為 column_indexer
。行 df.iloc[:, [0, 3]]
返回第一列和第四列。
在我們的情況下,顯示的信息是每位客戶的 Name
和 Age
:
df.iloc[:, [0, 3]]
客戶編號 |
名稱 |
年齡 |
C123 |
約翰·多 |
67 |
C234 |
佩特拉·穆勒 |
51 |
C345 |
阿里·汗 |
19 |
C456 |
瑪麗亞·岡薩雷斯 |
26 |
C567 |
大衛·李 |
40 |
使用 .iloc 選擇列的區段
在使用.iloc
進行切片選擇時,column_indexer
的邏輯與row_indexer
相同。在冒號後的整數代表的列不包含在輸出中。要檢索第二和第三列,代碼行應該如下所示:df.iloc[:, 1:3]
。
以下這行返回我們關於客戶的所有地理信息:
df.iloc[:, 1:3]
客戶ID |
國家 |
地區 |
C123 |
美國 |
北美洲 |
C234 |
德國 |
歐洲 |
C345 |
巴基斯坦 |
亞洲 |
C456 |
墨西哥 |
北美洲 |
C567 |
中國 |
亞洲 |
使用 .iloc 進行行和列的組合選擇
我們可以將學到的關於 .iloc
的內容整合起來,以組合行和列的選擇。同樣,可以返回單個單元格或子數據框。要返回第 3 行和第 4 列交叉處的單個單元格,我們輸入 df.iloc[2, 3]
。
就像使用 .loc
一樣,我們可以使用方括號將兩個索引器指定為列表,或者使用冒號作為切片。如果我們想使用條件表達式選擇行,技術上也可以使用 .iloc
,但不建議這樣做。使用標籤名稱和 .loc
通常更直觀且不易出錯。
這最後一個範例顯示了我們的數據框中第一、第二和第五行的 國家
、地區
和 年齡
:
df.iloc[[0,1,4], 1:4]
客戶 ID |
國家 |
地區 |
年齡 |
C123 |
美國 |
北美洲 |
67 |
C234 |
德國 |
歐洲 |
51 |
C567 |
中國 |
亞洲 |
40 |
.iloc vs .loc: When to Use Which
通常情況下,一個簡單的準則取決於您對數據框的了解程度:
- 當您知道行/列的標籤(名稱)時,請使用
.loc
。 - 當您知道行/列的整數位置時,請使用
.iloc
。 當您知道行/列的整數位置時,請使用.iloc
某些情況下,根據其性質,要使用.loc
或.iloc
更為適合。例如,使用整數進行行或列的迭代比使用標籤更容易且更直觀。正如我們已經提到的,基於列值條件過濾行的操作,使用列標籤名稱較少出錯。
偏好 .loc 的情況 |
偏好 .iloc 的情況 |
您的 DataFrame 具有有意義的索引/列名稱。 |
您正在按行/列的位置迭代。 |
您需要根據列值的條件進行篩選。 |
索引/列名對您的任務不重要。 |
KeyError、NameError 和 Index Error 使用 .loc 和 .iloc
讓我們看看可能出現的問題。在使用 .loc
時的一個常見問題是遇到 KeyError
。當我們嘗試訪問不存在於我們 DataFrame 中的行或列標籤時,就會出現此錯誤。為了避免這種情況,我們必須始終確保我們使用的標籤是準確的,並且與 DataFrame 中現有的標籤匹配,並且要仔細檢查有無拼寫錯誤。
此外,使用 .loc
指定的標籤時,始終重要使用引號。忘記引號將返回一個 NameError
。
如果在使用.iloc
時指定了超出DataFrame索引範圍的整數位置,則可能會出現IndexError
。這種情況發生在您嘗試訪問的索引不存在時,這可能是因為它超出了DataFrame中行或列的數量,或者因為它是一個負值。為了防止此錯誤,請檢查DataFrame的尺寸並在有效範圍內使用適當的索引值。
結論
我希望這篇博客對您有所幫助,並且現在您應該清楚了.loc
和.iloc
之間的區別。要瞭解更多,以下是一些不錯的下一步: