Pandas 提供了豐富的資料選擇與指定方法,能有效處理各種資料操作需求。除了基本的索引與切片方法外,本文將深入探討更進階的技巧,例如使用 filter 函式篩選特定標籤的資料、使用 select_dtypes 根據資料型別選擇欄位,以及使用布林遮罩選取資料子集。此外,更進一步說明如何運用 MultiIndex 進行多層次索引,並搭配 .loc 方法精確選擇和指定資料。這些技巧能大幅提升資料處理的效率與靈活性。

資料選擇與指定的高階技巧

在進行資料分析時,選擇正確的資料是非常重要的。pandas 提供了多種方法來選擇和操作資料。在本章中,我們將深入探討如何使用不同的技巧來選擇和指定資料。

使用 pd.DataFrame.filter 進行資料篩選

pd.DataFrame.filter 是一個專門用於從 pd.DataFrame 中選擇列或行的函式。它允許你根據標籤進行選擇。

如何使用

首先,讓我們建立一個 pd.DataFrame,其中索引和列都包含字串:

df = pd.DataFrame([
    [24, 180, "blue"],
    [42, 166, "brown"],
    [22, 160, "green"],
], columns=["age", "height_cm", "eye_color"], index=["Jack", "Jill", "Jayne"])

使用 pd.DataFrame.filter 選擇特定的列:

df.filter(["age", "eye_color"])

輸出:

      age eye_color
Jack   24      blue
Jill   42     brown
Jayne  22     green

你也可以使用 axis 引數來選擇行:

df.filter(["Jack", "Jill"], axis=0)

輸出:

     age  height_cm eye_color
Jack  24        180      blue
Jill  42        166     brown

此外,pd.DataFrame.filter 還支援使用 likeregex 引數進行更複雜的篩選。

使用 pd.DataFrame.select_dtypes 進行資料型別選擇

pd.DataFrame.select_dtypes 允許你根據資料型別選擇列。

如何使用

建立一個包含不同資料型別的 pd.DataFrame

df = pd.DataFrame([
    [0, 1.0, "2"],
    [4, 8.0, "16"],
], columns=["int_col", "float_col", "string_col"])

選擇整數型別的列:

df.select_dtypes("int")

輸出:

   int_col
0        0
1        4

你也可以選擇多種資料型別:

df.select_dtypes(include=["int", "float"])

輸出:

   int_col  float_col
0        0        1.0
1        4        8.0

使用布林陣列進行資料篩選

使用布林陣列(或稱為遮罩)是選擇資料子集的常見方法。

如何使用

建立一個布林遮罩和一個簡單的 pd.Series

mask = [True, False, True]
ser = pd.Series(range(3))

使用遮罩選擇 pd.Series 中的元素:

ser[mask]

輸出:

0    0
2    2
dtype: int64

對於 pd.DataFrame,布林遮罩可以用於選擇行或列。

使用多重索引進行資料選擇

pd.MultiIndex 支援階層式標籤,可以用於更複雜的資料選擇。

如何使用

建立一個 pd.MultiIndex 和一個簡單的 pd.Series

index = pd.MultiIndex.from_tuples([
    ("John", "Smith"),
    ("John", "Doe"),
    ("Jane", "Smith"),
])
ser = pd.Series(range(3), index=index)

使用 pd.DataFrame.loc 方法進行選擇,避免使用 pd.DataFrame[] 以減少混淆。

  flowchart TD
 A[開始] --> B{檢查資料}
 B -->|資料有效| C[處理資料]
 B -->|資料無效| D[回報錯誤]
 C --> E[完成處理]
 D --> E

圖表翻譯:

此圖示展示了一個基本的資料處理流程。流程始於「開始」階段,接著進行資料有效性檢查。若資料有效,系統會進入「處理資料」階段;若資料無效,則轉向「回報錯誤」階段。最後,無論資料處理成功與否,流程都會到達「完成處理」階段。此圖清晰地說明瞭程式中的條件分支邏輯以及不同處理路徑的銜接方式,幫助讀者理解整體處理邏輯。

內容解密:

此程式碼定義了一個名為 filter_data 的函式,用於使用布林陣列篩選資料。函式接收一個 pd.DataFrame 和一個布林遮罩作為輸入引數,傳回篩選後的資料。範例中建立了一個包含年齡、身高和眼睛顏色的 pd.DataFrame,並使用布林遮罩篩選出年齡小於 40 的資料。程式碼展示瞭如何使用布林陣列進行資料篩選,並傳回符合條件的資料子集。

Pandas 資料選擇與指定:深入 MultiIndex 與 .loc 使用技巧

在 Pandas 資料分析中,資料選擇與指定是非常重要的操作。本文將深入探討如何使用 .loc 方法對具有 MultiIndex 的 Series 和 DataFrame 進行資料選擇和指定。

MultiIndex 的基本概念

MultiIndex 是 Pandas 中一個強大的功能,允許我們在 Series 或 DataFrame 中使用多層索引。這使得資料的組織和選擇變得更加靈活和強大。

import pandas as pd

# 建立 MultiIndex
index = pd.MultiIndex.from_tuples([
    ("John", "Smith"),
    ("John", "Doe"),
    ("Jane", "Doe"),
    ("Stephen", "Smith"),
], names=["first_name", "last_name"])

# 建立 Series
ser = pd.Series(range(4), index=index)
print(ser)

輸出:

first_name  last_name
John       Smith      0
           Doe        1
Jane       Doe        2
Stephen    Smith      3
dtype: int64

使用 .loc 進行資料選擇

.loc 方法允許我們根據索引標籤進行資料選擇。對於具有 MultiIndex 的 Series 或 DataFrame,我們可以使用 tuple 來指定多個層級的索引。

選擇特定索引值的資料

# 選擇 first_name 為 "Jane" 且 last_name 為 "Doe" 的資料
print(ser.loc[("Jane", "Doe")])

輸出:

2

選擇多個索引值的資料

# 選擇多個特定索引的資料
print(ser.loc[[("John", "Smith"), ("Jane", "Doe")]])

輸出:

first_name  last_name
John       Smith      0
Jane       Doe        2
dtype: int64

使用 slice(None) 進行層級選擇

# 選擇第二層索引為 "Doe" 的所有資料
print(ser.loc[(slice(None), "Doe")])

輸出:

first_name  last_name
John       Doe        1
Jane       Doe        2
dtype: int64

使用 pd.IndexSlice 簡化語法

ixsl = pd.IndexSlice
print(ser.loc[ixsl[:, ["Doe"]]])

輸出:

first_name  last_name
John       Doe        1
Jane       Doe        2
dtype: int64

DataFrame 中的 MultiIndex 選擇

當 DataFrame 同時在行和列上使用 MultiIndex 時,.loc 方法同樣適用。

# 建立具有 MultiIndex 的 DataFrame
row_index = pd.MultiIndex.from_tuples([
    ("John", "Smith"),
    ("John", "Doe"),
    ("Jane", "Doe"),
    ("Stephen", "Smith"),
], names=["first_name", "last_name"])

col_index = pd.MultiIndex.from_tuples([
    ("music", "favorite"),
    ("music", "last_seen_live"),
    ("art", "favorite"),
], names=["art_type", "category"])

df = pd.DataFrame([
    ["Swift", "Swift", "Matisse"],
    ["Mozart", "T. Swift", "Van Gogh"],
    ["Beatles", "Wonder", "Warhol"],
    ["Jackson", "Dylan", "Picasso"],
], index=row_index, columns=col_index)

# 同時選擇行和列
row_idxer = (slice(None), "Smith")
col_idxer = (slice(None), "favorite")
print(df.loc[row_idxer, col_idxer])

輸出:

art_type    music      art
category  favorite  favorite
first_name last_name          
John       Smith     Swift    Matisse
Stephen    Smith    Jackson   Picasso

資料指定操作

.loc.iloc 不僅可以用於資料選擇,還可以用於資料指定。

# 建立簡單的 Series
ser = pd.Series(range(3), index=list("abc"))

# 使用 .loc 進行資料指定
ser.loc["b"] = 42
print(ser)

輸出:

a      0
b     42
c      2
dtype: int64

效能考量

雖然 Pandas 主要針對讀取和探索資料進行了最佳化,但在必要時仍可使用 .loc.iloc 進行資料變更。需要注意的是,頻繁的資料變更操作可能會影響效能。

圖表翻譯:

此圖示展示了使用 .loc 方法進行資料選擇的流程。首先判斷資料是否為 MultiIndex,如果是則使用 tuple 進行選擇。接著根據是否需要多層選擇來決定使用 slice(None) 或 pd.IndexSlice。最後完成資料選擇後可進行資料指定操作。此流程清晰地展示了不同情況下如何靈活使用 .loc 方法進行資料操作。

資料選擇與指定

在 pandas 中,資料的選擇與指定是非常基本且重要的操作。無論是對 Series 或是 DataFrame 進行操作,都需要了解如何正確地選擇和指定資料。

Series 的索引指定

在 pandas 中,pd.Series 是一種一維的標籤化陣列。對 pd.Series 指定可以使用 .loc.iloc 兩種方法。

使用 .loc 指定

.loc 是根據標籤的索引,可以用來根據索引標籤進行指定。

import pandas as pd

# 建立一個簡單的 Series
ser = pd.Series([0, 2, 2], index=list('abc'))
print("原始 Series:")
print(ser)

# 使用 .loc 指定
ser.loc["b"] = 42
print("\n使用 .loc 指定後的 Series:")
print(ser)

圖表 1:.loc 指定流程圖

  flowchart TD
 A[開始] --> B{檢查索引標籤}
 B -->|存在| C[指定]
 B -->|不存在| D[新增索引並指定]
 C --> E[結束]
 D --> E

圖表翻譯:

此圖示展示了使用 .loc 指定的流程。首先檢查索引標籤是否存在,若存在則直接指定;若不存在,則新增該索引並指定。最後結束操作。

使用 .iloc 指定

.iloc 是根據位置的索引,用於根據位置進行指定。

# 使用 .iloc 指定
ser.iloc[2] = -42
print("\n使用 .iloc 指定後的 Series:")
print(ser)

圖表 2:.iloc 指定流程圖

  flowchart TD
 A[開始] --> B{檢查位置索引}
 B -->|有效| C[指定]
 B -->|無效| D[報錯]
 C --> E[結束]
 D --> E

圖表翻譯:

此圖示展示了使用 .iloc 指定的流程。首先檢查位置索引是否有效,若有效則指定;若無效,則報錯。最後結束操作。

DataFrame 的欄位指定

pd.DataFrame 指定是常見的操作,可以新增或修改欄位。

新增欄位

可以使用 [] 運算元新增欄位。

# 建立一個簡單的 DataFrame
df = pd.DataFrame({"col1": [1, 2, 3]})
print("原始 DataFrame:")
print(df)

# 新增欄位
df["new_column1"] = 42
print("\n新增常數欄位後的 DataFrame:")
print(df)

df["new_column2"] = list("abc")
print("\n新增列表欄位後的 DataFrame:")
print(df)

圖表 3:新增欄位流程圖

  flowchart TD
 A[開始] --> B{檢查資料長度}
 B -->|匹配| C[新增欄位]
 B -->|不匹配| D[報錯]
 C --> E[結束]
 D --> E

圖表翻譯:

此圖示展示了新增欄位時的檢查流程。首先檢查資料長度是否與 DataFrame 的列數匹配,若匹配則新增欄位;若不匹配,則報錯。最後結束操作。

使用 .assign() 方法鏈式指定

.assign() 方法允許在方法鏈中新增欄位。

# 使用 .assign() 新增欄位
df = pd.DataFrame([[0, 1], [2, 4]], columns=list("ab"))
result = df.mul(2).add(42).assign(chained_c=lambda df: df["b"] - 3)
print("\n使用 .assign() 方法鏈式指定後的 DataFrame:")
print(result)

圖表 4:.assign() 方法鏈流程圖

  flowchart TD
 A[開始] --> B[乘以 2]
 B --> C[加上 42]
 C --> D[新增欄位 chained_c]
 D --> E[結束]

圖表翻譯:

此圖示展示了使用 .assign() 方法鏈的流程。首先對 DataFrame 進行乘以 2 的操作,接著加上 42,然後新增欄位 chained_c,最後結束操作。

資料型別的選擇與最佳化

資料型別的選擇對於 pandas 的效能和資料品質至關重要。瞭解不同的資料型別及其實作方式,可以幫助選擇最合適的型別以最佳化應用。

pandas 資料型別的演進

pandas 最初建立在 NumPy 的型別系統之上,但 NumPy 的型別系統不支援缺失值,且缺乏對字串的良好支援。從 pandas 0.23 版本開始,引入了新的資料型別以支援缺失值,到了 1.0 版本,實作了自己的字串資料型別。從 2.0 版本開始,pandas 允許使用 Apache Arrow 專案的資料型別,這些型別標準化了不同工具和語言之間的資料表示。

資料型別選擇的重要性

選擇正確的資料型別可以確保資料品質,並啟用高效能的演算法。不同的資料型別有不同的實作方式,瞭解這些實作方式可以幫助做出最佳選擇。

資料型別管理最佳實踐

在資料分析領域中,選擇適當的資料型別對於效能和準確性至關重要。本文將深入探討 pandas 中不同資料型別的使用時機與最佳實踐,特別著重於擴充型別、Arrow 型別和 NumPy 型別的比較。

整數型別

整數型別是資料分析中最基本的型別之一,用於表示整數值。pandas 提供了多種整數型別,包括有符號和無符號整數,支援的位元寬度從 8 位到 64 位不等。

# 建立 64 位元整數序列
s = pd.Series(range(3), dtype=pd.Int64Dtype())
print(s)
# 輸出:
# 0    0
# 1    1
# 2    2
# dtype: Int64

# 使用較小的資料型別
s_small = pd.Series(range(3), dtype=pd.Int8Dtype())
print(s_small)
# 輸出:
# 0    0
# 1    1
# 2    2
# dtype: Int8

內容解密:

此範例展示瞭如何建立不同位元寬度的整數序列。選擇適當的整數型別可以在保證資料正確性的同時,最佳化記憶體使用。表格 3.1 詳細列出了不同整數型別的上下限。

  flowchart TD
 A[選擇整數型別] --> B{資料範圍}
 B -->|小於 128| C[使用 Int8]
 B -->|大於 127 且小於 32768| D[使用 Int16]
 B -->|大於 32767 且小於 2147483648| E[使用 Int32]
 B -->|更大範圍| F[使用 Int64]

圖表翻譯:

此圖表展示了根據資料範圍選擇適當整數型別的決策流程。從最小的 Int8 到最大的 Int64,不同的型別適用於不同的資料場景。正確選擇可以有效降低記憶體使用。

浮點數型別

浮點數型別用於表示實數,適用於需要小數精確度的計算。pandas 支援 32 位和 64 位浮點數型別。

# 建立浮點數序列
s_float = pd.Series([3.14, 0.333333333, -123.456], dtype=pd.Float64Dtype())
print(s_float)
# 輸出:
# 0      3.14
# 1  0.333333
# 2  -123.456
# dtype: Float64

內容解密:

浮點數運算存在精確度問題,特別是在極端值計算時。對於需要絕對精確度的場景,應考慮使用 PyArrow 的 decimal 型別。

資料型別選擇建議

  1. 優先使用 pandas 擴充型別:當可用的時候,擴充型別提供了更好的效能和功能。
  2. 使用 Arrow 型別處理複雜資料:對於 pandas 擴充型別無法滿足的需求,Arrow 型別提供了更多進階功能。
  3. 最後使用 NumPy 型別:NumPy 型別作為備選方案,但在某些情況下可能存在效能或功能限制。

各型別比較

型別類別主要優點適用場景
pandas 擴充型別更好的缺失值支援、更豐富的功能大多數資料分析場景
Arrow 型別高效能、支援複雜資料結構大型資料集、複雜資料處理
NumPy 型別相容性好、基礎運算效能佳簡單數值計算、舊有系統相容