Pandas是資料科學領域中不可或缺的工具,其提供的資料重塑與轉換功能,讓資料處理更具彈性。從JSON資料的載入與處理,到使用explode、merge及T等方法進行資料的重塑,Pandas都能夠有效地協助資料分析師整理資料。此外,資料分組與聚合分析也是Pandas的強項,groupby搭配agg、transform及apply等方法,可以針對不同需求進行資料彙整與計算,大幅提升資料分析的效率。

資料重塑與轉換:深入探討pandas的強大功能

在資料分析和處理的過程中,資料的重塑和轉換是至關重要的步驟。pandas函式庫提供了多種強大的工具來實作這些操作,從而使資料分析師能夠更靈活地處理和分析資料。本章將深入探討pandas中的資料重塑和轉換技術,包括使用JSON資料、資料爆炸(DataFrame.explode)、資料合併(pd.merge)以及資料轉置(pd.DataFrame.T)等。

使用JSON資料和資料爆炸技術

在處理半結構化資料時,JSON是一種常見的資料格式。假設我們有一個來自HR系統的JSON資料,描述了公司員工的組織架構:

[
 {
 "employee_id": 1,
 "first_name": "John",
 "last_name": "Smith",
 "direct_reports": [2, 3]
 },
 {
 "employee_id": 2,
 "first_name": "Jane",
 "last_name": "Doe",
 "direct_reports": []
 },
 {
 "employee_id": 3,
 "first_name": "Joe",
 "last_name": "Schmoe",
 "direct_reports": []
 }
]

我們可以使用pandas的DataFrame建構子將這個JSON資料載入到DataFrame中:

import pandas as pd

data = [
 {"employee_id": 1, "first_name": "John", "last_name": "Smith", "direct_reports": [2, 3]},
 {"employee_id": 2, "first_name": "Jane", "last_name": "Doe", "direct_reports": []},
 {"employee_id": 3, "first_name": "Joe", "last_name": "Schmoe", "direct_reports": []}
]

df = pd.DataFrame(data)
print(df)

輸出結果如下:

 employee_id first_name last_name direct_reports
0 1 John Smith [2, 3]
1 2 Jane Doe []
2 3 Joe Schmoe []

資料爆炸:將列表欄位拆分成多行

使用DataFrame.explode方法,我們可以將direct_reports欄位中的列表拆分成多行:

exploded_df = df.explode("direct_reports").convert_dtypes(dtype_backend="numpy_nullable")
print(exploded_df)

輸出結果如下:

 employee_id first_name last_name direct_reports
0 1 John Smith 2
0 1 John Smith 3
1 2 Jane Doe <NA>
2 3 Joe Schmoe <NA>

合併資料:取得直接下屬的詳細資訊

接著,我們可以使用pd.mergeexploded_df與原始DataFrame合併,取得直接下屬的詳細資訊:

merged_df = pd.merge(
 exploded_df,
 df.drop(columns=["direct_reports"]),
 how="left",
 left_on=["direct_reports"],
 right_on=["employee_id"],
 suffixes=("", "_direct_report"),
)
print(merged_df)

輸出結果如下:

 employee_id first_name last_name direct_reports employee_id_direct_report first_name_direct_report last_name_direct_report
0 1 John Smith 2 2 Jane Doe
1 1 John Smith 3 3 Joe Schmoe
2 2 Jane Doe <NA> <NA> <NA> <NA>
3 3 Joe Schmoe <NA> <NA> <NA> <NA>

資料轉置:使用pd.DataFrame.T

資料轉置是另一種常見的資料重塑操作,它可以將DataFrame的行和列互換。假設我們有一個簡單的DataFrame:

df = pd.DataFrame([
 [1, 2, 3],
 [4, 5, 6],
], columns=list("xyz"), index=list("ab"))
print(df)

輸出結果如下:

 x y z
a 1 2 3
b 4 5 6

使用df.T可以將其轉置:

transposed_df = df.T
print(transposed_df)

輸出結果如下:

 a b
x 1 4
y 2 5
z 3 6

為什麼要進行資料轉置?

資料轉置在某些情況下非常有用,例如:

  1. 提高效能:在某些運算中,按列操作比按行操作更高效。例如,使用axis=1引數可能會降低效能,而轉置後再進行操作可以提高效率。
import numpy as np

np.random.seed(42)
df = pd.DataFrame(np.random.randint(10, size=(2, 10000)), index=list("ab"))
print(df.sum(axis=1)) # 按行求和
print(df.T.sum()) # 轉置後按列求和,效率更高
  1. 改變資料結構以適應特定分析需求:某些分析方法或函式可能需要特定的資料結構,轉置可以幫助滿足這些需求。

使用PyArrow的結構資料型別

PyArrow提供了一種結構資料型別(struct),可以用於表示複雜的巢狀資料結構。結合pandas使用時,可以利用pd.Series.struct.explode方法將結構中的欄位展開為新的列:

import pyarrow as pa

dtype = pd.ArrowDtype(pa.struct([
 ("int_col", pa.int64()),
 ("str_col", pa.string()),
 ("float_col", pa.float64()),
]))

ser = pd.Series([
 {"int_col": 42, "str_col": "Hello, ", "float_col": 3.14159},
 {"int_col": 555, "str_col": "world!", "float_col": 3.14159},
], dtype=dtype)

exploded_ser = ser.struct.explode()
print(exploded_ser)

輸出結果如下:

 int_col str_col float_col
0 42 Hello, 3.14159
1 555 world! 3.14159

這種方法在處理巢狀資料結構時非常有用,可以簡化資料的解析和處理過程。

圖表說明

  flowchart TD
 A[開始] --> B{檢查資料格式}
 B -->|JSON資料| C[載入JSON資料到DataFrame]
 B -->|其他格式| D[轉換資料格式]
 C --> E[使用DataFrame.explode進行資料爆炸]
 E --> F[合併資料以取得更多資訊]
 F --> G[使用DataFrame.T進行資料轉置]
 G --> H[分析轉置後的資料]

圖表翻譯:

此圖示展示了資料重塑和轉換的一般流程。首先檢查資料的格式,如果是JSON資料,則直接載入到DataFrame中;如果是其他格式,則需要先進行格式轉換。接著,使用DataFrame.explode方法將巢狀資料結構展開。隨後,可以透過合併資料來取得更多相關資訊。最後,利用DataFrame.T進行資料轉置,以便於進行進一步的分析和處理。整個流程展示了資料從原始狀態到可分析狀態的轉換過程。

Pandas 資料分組與聚合分析

在資料分析過程中,資料分組(Group By)是一項重要的技術,能夠協助分析師快速彙總資料、找出不同群組間的模式,並進行比較。Pandas 提供了強大的 groupby 功能,讓使用者能夠輕鬆地對資料進行分組並套用各種聚合函式。

簡單的分組與聚合範例

首先,我們建立一個簡單的 DataFrame 來示範基本的分組與聚合操作:

import pandas as pd

# 建立範例資料
data = [
    ["group_a", 0],
    ["group_a", 2],
    ["group_b", 1],
    ["group_b", 3],
    ["group_b", 5],
]
df = pd.DataFrame(data, columns=["group", "value"])

# 顯示原始資料
print("原始資料:")
print(df)

# 進行分組並計算總和
grouped_sum = df.groupby("group").sum()
print("\n分組總和:")
print(grouped_sum)

程式碼說明:

  1. 我們首先匯入 pandas 套件並建立一個簡單的 DataFrame。
  2. 使用 groupby 方法對 “group” 欄位進行分組。
  3. 套用 sum 方法計算每個群組的 “value” 總和。
  4. 輸出結果顯示每個群組的總和。

多欄位分組與不同聚合函式的應用

在實際應用中,我們經常需要對多個欄位進行聚合計算。以下範例示範如何對銷售資料進行分組並計算多個欄位的聚合值:

# 建立銷售資料
sales_data = [
    ["North", "Widget A", "Jan", 10, 2],
    ["North", "Widget B", "Jan", 4, 0],
    ["South", "Widget A", "Jan", 8, 3],
    ["South", "Widget B", "Jan", 12, 8],
    ["North", "Widget A", "Feb", 3, 0],
    ["North", "Widget B", "Feb", 7, 0],
    ["South", "Widget A", "Feb", 11, 2],
    ["South", "Widget B", "Feb", 13, 4],
]
df_sales = pd.DataFrame(sales_data, columns=["region", "widget", "month", "sales", "returns"])

# 對 widget 進行分組並計算銷售額和退貨量的總和
widget_summary = df_sales.groupby("widget")[["sales", "returns"]].sum()
print("\n各商品銷售與退貨彙總:")
print(widget_summary)

程式碼說明:

  1. 建立包含地區、商品、月份、銷售額和退貨量的 DataFrame。
  2. 使用 groupby 對 “widget” 欄位進行分組。
  3. 選擇 “sales” 和 “returns” 欄位進行聚合計算。
  4. 輸出結果顯示各商品的銷售與退貨總量。

自訂聚合欄位名稱

Pandas 允許我們自訂聚合後的欄位名稱:

# 自訂聚合結果的欄位名稱
custom_agg = df_sales.groupby("widget").agg(
    total_sales=pd.NamedAgg(column="sales", aggfunc="sum"),
    total_returns=pd.NamedAgg(column="returns", aggfunc="sum")
)
print("\n自訂欄位名稱的聚合結果:")
print(custom_agg)

程式碼說明:

  1. 使用 agg 方法進行聚合計算。
  2. 透過 NamedAgg 自訂輸出欄位的名稱和聚合邏輯。
  3. 同時計算銷售額和退貨量的總和。

資料轉換操作

除了聚合操作,Pandas 還支援資料轉換(Transformation):

# 計算每個群組的總和並轉換回原始資料的形狀
group_sum_transform = df.groupby("group").transform("sum")
print("\n群組總和的轉換結果:")
print(group_sum_transform)

程式碼說明:

  1. 使用 transform 方法將聚合結果轉換回與原始資料相同的形狀。
  2. 這種操作便於進行群組內的比例計算。

視覺化說明

以下 Mermaid 圖表展示了分組操作的流程:

  flowchart TD
    A[原始資料] --> B{分組條件}
    B -->|group_a| C[計算聚合值]
    B -->|group_b| D[計算聚合值]
    C --> E[合併結果]
    D --> E
    E --> F[輸出結果]

圖表說明:

此圖示展示了資料分組與聚合的完整流程。首先,原始資料根據指定的分組條件進行分類別。接著,對每個群組分別計算所需的聚合值。最後,將各群組的計算結果合併並輸出。這種流程幫助我們理解資料是如何被處理和彙總的。

進階應用場景

在實際應用中,我們可以結合多種聚合操作來滿足複雜的分析需求。例如,同時計算不同商品在各個地區的銷售表現:

# 多重分組與聚合
region_widget_sales = df_sales.groupby(["region", "widget"]).agg({
    "sales": "sum",
    "returns": "sum"
})
print("\n各地區商品銷售與退貨分析:")
print(region_widget_sales)

程式碼說明:

  1. 使用多重索引進行分組。
  2. 同時計算銷售額和退貨量的總和。
  3. 結果按照地區和商品進行分類別彙總。

使用Pandas進行資料分組與聚合分析

在資料分析過程中,分組與聚合是非常重要的操作。Pandas提供了強大的groupby功能,可以對資料進行分組並應用各種聚合函式。本篇文章將深入探討Pandas中的分組與聚合操作,並提供實用的範例。

分組與聚合的基本概念

分組是指根據某個或某些欄位將資料分成不同的群組,而聚合則是對每個群組進行計算以獲得彙總結果。Pandas的groupby方法可以輕鬆實作這兩個步驟。

使用groupby進行簡單分組

以下是一個簡單的範例,展示如何使用groupby對資料進行分組並計算總和:

import pandas as pd

# 建立範例資料
data = {
    'widget': ['Widget A', 'Widget A', 'Widget B', 'Widget B'],
    'region': ['North', 'South', 'North', 'South'],
    'sales': [10, 15, 8, 20],
    'returns': [2, 3, 0, 5]
}
df = pd.DataFrame(data)

# 按照widget欄位進行分組並計算sales和returns的總和
grouped_df = df.groupby('widget').agg(
    sales_total=pd.NamedAgg(column='sales', aggfunc='sum'),
    returns_total=pd.NamedAgg(column='returns', aggfunc='sum')
)

print(grouped_df)

內容解密:

此範例首先建立了一個包含商品銷售資料的DataFrame。接著,使用groupby方法按照widget欄位進行分組,並使用agg方法計算每個分組的salesreturns總和。pd.NamedAgg用於指定聚合的欄位和函式,並可自定義輸出欄位的名稱。

多重分組

除了單一欄位的分組外,Pandas也支援多重欄位的分組。例如,我們可以同時按照widgetregion進行分組:

# 按照widget和region進行分組
grouped_df_multi = df.groupby(['widget', 'region']).agg(
    sales_total=pd.NamedAgg('sales', 'sum'),
    returns_total=pd.NamedAgg('returns', 'sum')
)

print(grouped_df_multi)

內容解密:

在此範例中,我們對widgetregion兩個欄位進行分組。這樣可以獲得每個商品在不同地區的銷售和退貨總額。多重分組可以提供更細緻的資料分析結果。

自定義聚合函式

有時,內建的聚合函式無法滿足需求,這時就需要自定義聚合函式。例如,我們可以定義一個計算眾數(mode)的函式:

def scalar_or_list_mode(ser: pd.Series):
    result = ser.mode()
    if len(result) > 1:
        return result.tolist()
    elif len(result) == 1:
        return result.iloc[0]
    return pd.NA

# 使用自定義的眾數函式進行聚合
df_mode = df.groupby('widget').agg(
    sales_mode=pd.NamedAgg(column='sales', aggfunc=scalar_or_list_mode)
)

print(df_mode)

內容解密:

此範例定義了一個名為scalar_or_list_mode的函式,用於計算眾數。如果眾數有多個,則傳回一個列表;否則傳回單一值。這個函式被用於對sales欄位進行聚合,展示瞭如何在Pandas中使用自定義聚合函式。

使用apply進行更複雜的操作

除了聚合操作外,Pandas的apply方法允許我們對分組資料進行更複雜的操作。例如:

def mode_for_apply(df: pd.DataFrame):
    return df['sales'].mode()

# 對每個分組應用mode_for_apply函式
df_apply_result = df.groupby('widget').apply(mode_for_apply, include_groups=False)

print(df_apply_result)

內容解密:

此範例定義了一個名為mode_for_apply的函式,用於計算每個分組的sales欄位的眾數。apply方法將此函式應用於每個分組,傳回眾數值。這種方法比簡單的聚合更靈活,可以用於更複雜的資料處理。

Mermaid圖表展示分組與聚合流程

  flowchart TD
    A[開始] --> B{選擇分組欄位}
    B -->|單一欄位| C[進行單一欄位分組]
    B -->|多重欄位| D[進行多重欄位分組]
    C --> E[應用聚合函式]
    D --> E
    E --> F[輸出結果]

圖表翻譯:

此圖表展示了使用Pandas進行資料分組與聚合的流程。首先選擇要進行分組的欄位,可以是單一欄位或多重欄位。接著,對選定的資料進行分組並應用聚合函式。最後,輸出聚合結果。這種流程圖幫助理解分組與聚合操作的整體邏輯。