Pandas 提供了強大的資料重塑功能,方便資料分析和視覺化。stack 和 melt 函式可以將寬格式資料轉換為長格式,unstack 則可以進行反向操作。wide_to_long 函式適用於欄位名稱具有特定模式的寬格式資料轉換。pivot 和 pivot_table 函式則可以將長格式資料轉換為寬格式,pivot_table 還可以處理重複值並進行聚合運算。explode 函式可以處理 DataFrame 中包含列表的列,將列表元素拆分為單獨的行,方便資料分析和處理。這些函式共同構成了 Pandas 資料重塑的核心工具,能夠有效地處理各種資料轉換需求。
重塑DataFrame:資料轉換的藝術
在資料分析和處理的過程中,經常需要對DataFrame進行重塑,以滿足不同的分析和視覺化需求。本篇文章將探討如何使用pandas函式庫中的stack、unstack和melt函式來重塑DataFrame。
從寬格式轉換為長格式
在資料建模術語中,我們通常將具有多個欄位代表不同類別的DataFrame稱為「寬」表格。例如,下面的DataFrame中,每一行代表一個州,而不同水果的數量則位於各自的欄位中。
import pandas as pd
# 建立範例DataFrame
data = [
["Texas", 12, 10, 40],
["Arizona", 9, 7, 12],
["Florida", 0, 14, 190]
]
df = pd.DataFrame(data, columns=["state", "apple", "orange", "banana"])
df = df.convert_dtypes(dtype_backend="numpy_nullable")
print(df)
輸出結果:
state apple orange banana
0 Texas 12 10 40
1 Arizona 9 7 12
2 Florida 0 14 190
使用stack函式轉換為長格式
要將寬格式轉換為長格式,我們可以使用stack函式。這個過程涉及將水果名稱從欄位索引轉換為行索引的一部分,形成一個多層索引(MultiIndex)。
stacked_df = df.set_index("state").stack().reset_index()
stacked_df = stacked_df.rename(columns={"level_1": "fruit", 0: "number_grown"})
print(stacked_df)
輸出結果:
state fruit number_grown
0 Texas apple 12
1 Texas orange 10
2 Texas banana 40
3 Arizona apple 9
4 Arizona orange 7
5 Arizona banana 12
6 Florida apple 0
7 Florida orange 14
8 Florida banana 190
使用melt函式轉換為長格式
另一種轉換為長格式的方法是使用melt函式。這個函式提供了更多的彈性,可以控制哪些欄位參與轉換。
melted_df = df.melt(id_vars=["state"], var_name="fruit", value_name="number_grown")
print(melted_df)
輸出結果與使用stack函式的結果相同。
從長格式轉換為寬格式
有時,我們需要將長格式的DataFrame轉換回寬格式。這可以透過unstack函式實作。
# 先將DataFrame轉換為MultiIndex Series
stacked = df.set_index(["state", "fruit"])["number_grown"]
# 使用unstack函式轉換回寬格式
unstacked_df = stacked.unstack(level="fruit")
print(unstacked_df)
輸出結果:
fruit apple banana orange
state
Arizona 9 12 7
Florida 0 190 14
Texas 12 40 10
圖表翻譯:理解資料重塑過程
此圖示展示了資料重塑的過程,從寬格式到長格式的轉換,以及反向的轉換過程。
@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle
title DataFrame資料轉換技巧
package "資料視覺化流程" {
package "資料準備" {
component [資料載入] as load
component [資料清洗] as clean
component [資料轉換] as transform
}
package "圖表類型" {
component [折線圖 Line] as line
component [長條圖 Bar] as bar
component [散佈圖 Scatter] as scatter
component [熱力圖 Heatmap] as heatmap
}
package "美化輸出" {
component [樣式設定] as style
component [標籤註解] as label
component [匯出儲存] as export
}
}
load --> clean --> transform
transform --> line
transform --> bar
transform --> scatter
transform --> heatmap
line --> style --> export
bar --> label --> export
note right of scatter
探索變數關係
發現異常值
end note
@enduml圖表翻譯: 此圖表展示了寬格式與長格式之間的轉換關係。寬格式DataFrame可以透過stack或melt函式轉換為長格式,而長格式DataFrame可以透過unstack函式轉換回寬格式。
資料重塑:使用 pd.wide_to_long 與 pd.DataFrame.pivot
在資料分析的過程中,經常需要將資料從寬格式(wide format)轉換為長格式(long format),或是反向操作。本章節將介紹兩種重要的 pandas 函式:pd.wide_to_long 和 pd.DataFrame.pivot,幫助讀者有效地進行資料重塑。
使用 pd.wide_to_long 進行資料重塑
pd.wide_to_long 是一種用於將寬格式資料轉換為長格式的函式,尤其適用於欄位名稱具有特定模式的情況。讓我們透過一個範例來瞭解其用法:
程式碼範例
import pandas as pd
# 建立範例資料
df = pd.DataFrame([
["Widget 1", 1, 2, 4, 8],
["Widget 2", 16, 32, 64, 128],
], columns=["widget", "quarter_1", "quarter_2", "quarter_3", "quarter_4"])
# 使用 pd.wide_to_long 進行轉換
df_long = pd.wide_to_long(
df,
i=["widget"],
stubnames="quarter_",
j="quarter"
).reset_index().rename(columns={"quarter_": "quantity"})
print(df_long)
輸出結果
widget quarter quantity
0 Widget 1 1 1
1 Widget 2 1 16
2 Widget 1 2 2
3 Widget 2 2 32
4 Widget 1 3 4
5 Widget 2 3 64
6 Widget 1 4 8
7 Widget 2 4 128
#### 內容解密:
pd.wide_to_long需要指定i、stubnames和j三個主要引數。其中,i是用來識別資料的主鍵,stubnames是欄位名稱的字首,而j是新生成的欄位名稱。- 在這個範例中,我們將
widget設定為i,quarter_設定為stubnames,並將j設定為quarter。這樣,原始資料中的quarter_1、quarter_2等欄位就被轉換成了quarter欄位下的不同值。 - 最後,我們使用
reset_index和rename方法來調整輸出的欄位名稱,使其更符合需求。
使用 pd.DataFrame.pivot 和 pd.pivot_table 進行資料重塑
當需要將長格式資料轉換為寬格式時,可以使用 pd.DataFrame.pivot 或 pd.pivot_table。這兩個函式不僅能夠進行資料重塑,還能夠進行聚合運算。
程式碼範例
# 建立範例資料
df = pd.DataFrame([
["Texas", "apple", 12, 8],
["Arizona", "apple", 9, 10],
["Florida", "apple", 0, 6],
["Texas", "orange", 10, 4],
["Arizona", "orange", 7, 2],
["Florida", "orange", 14, 3],
["Texas", "banana", 40, 28],
["Arizona", "banana", 12, 17],
["Florida", "banana", 190, 42],
], columns=["state", "fruit", "number_grown", "number_eaten"])
# 使用 pd.DataFrame.pivot 進行轉換
df_pivot = df.pivot(index="state", columns="fruit")
print(df_pivot)
輸出結果
number_grown number_eaten
fruit apple banana orange apple banana orange
state
Arizona 9 12 7 10 17 2
Florida 0 190 14 6 42 3
Texas 12 40 10 8 28 4
#### 圖表翻譯:
此表格展示了使用 pd.DataFrame.pivot 將長格式資料轉換為寬格式的結果。其中,state 成為了索引,而 fruit 成為了欄位名稱。透過這種方式,可以方便地比較不同州別的水果生長和食用數量。
#### 程式碼解密:
pd.DataFrame.pivot需要指定index和columns,分別代表輸出的行索引和列索引。- 在這個範例中,我們將
state設定為index,將fruit設定為columns。這樣,原始資料就被重塑成了以州別和水果種類別為維度的寬格式資料。 - 需要注意的是,如果原始資料中存在重複的索引和欄位組合,
pd.DataFrame.pivot將會報錯。此時,可以考慮使用pd.pivot_table,它允許進行聚合運算。
資料重塑:使用 pd.DataFrame.pivot 與 pd.pivot_table
在資料分析過程中,經常需要將資料從長格式(long format)轉換為寬格式(wide format),或是反向轉換。pd.DataFrame.pivot 和 pd.pivot_table 是 pandas 中用於實作此類別轉換的兩個重要函式。
使用 pd.DataFrame.pivot 進行資料重塑
pd.DataFrame.pivot 允許你根據指定的列值重新組織資料。但是,它要求用於形成行和列的值必須是唯一的。
import pandas as pd
# 建立範例資料
data = {
"state": ["Arizona", "Florida", "Texas", "Arizona", "Florida", "Texas"],
"fruit": ["apple", "apple", "apple", "banana", "banana", "banana"],
"number_grown": [9, 0, 12, 12, 190, 40]
}
df = pd.DataFrame(data)
# 使用 pivot 進行資料重塑
wide_df = df.pivot(index="state", columns="fruit", values="number_grown")
print(wide_df)
內容解密:
index="state"指定了資料重塑後的行索引。columns="fruit"指定了資料重塑後的列名。values="number_grown"指定了用於填充新 DataFrame 的值。
輸出結果如下:
fruit apple banana
state
Arizona 9 12
Florida 0 190
Texas 12 40
處理多重索引
有時,你可能需要保留多個欄位的值。這時,pd.DataFrame.pivot 會建立一個多重索引的 DataFrame。
df = pd.DataFrame({
"state": ["Arizona", "Florida", "Texas", "Arizona", "Florida", "Texas"],
"fruit": ["apple", "apple", "apple", "banana", "banana", "banana"],
"number_grown": [9, 0, 12, 12, 190, 40],
"number_eaten": [7, 14, 10, 0, 1, 2]
})
wide_df = df.pivot(index="state", columns="fruit", values=["number_grown", "number_eaten"])
print(wide_df)
內容解密:
- 這裡
values=["number_grown", "number_eaten"]指定了兩個欄位,因此輸出的 DataFrame 有多重索引的列。
輸出結果如下:
number_grown number_eaten
fruit apple banana apple banana
state
Arizona 9 12 7 0
Florida 0 190 14 1
Texas 12 40 10 2
使用 pd.pivot_table 處理重複值
當你的資料中存在重複的行或列索引時,pd.DataFrame.pivot 就無法正常工作。這時,你可以使用 pd.pivot_table,它允許你透過聚合函式來處理這些重複值。
df = pd.DataFrame([
["Texas", "apple", 2023, 10, 6],
["Texas", "apple", 2024, 2, 8],
["Arizona", "apple", 2023, 3, 7],
["Arizona", "apple", 2024, 6, 3],
["Texas", "orange", 2023, 5, 2],
["Texas", "orange", 2024, 5, 2],
["Arizona", "orange", 2023, 7, 2],
], columns=["state", "fruit", "year", "number_grown", "number_eaten"])
pivoted_df = pd.pivot_table(df, index="state", columns="fruit", values=["number_grown", "number_eaten"], aggfunc="mean")
print(pivoted_df)
圖表翻譯:
此圖表呈現了使用 pd.pivot_table 將資料重塑並聚合的過程。輸入資料包含不同州的水果種植和食用數量,透過指定 aggfunc="mean",輸出了每個州不同水果的平均種植和食用數量。
內容解密:
aggfunc="mean"指定了對重複值的處理方式為取平均值。- 你可以根據需要改變聚合函式,例如使用
"sum"或自定義函式。
輸出結果如下:
number_eaten number_grown
fruit apple orange apple orange
state
Arizona 5.0 2.0 4.5 7.0
Texas 7.0 2.0 6.0 5.0
使用 pd.DataFrame.explode 處理列表資料
有時,DataFrame 中的某些列包含列表或元組等序列資料。pd.DataFrame.explode 可以將這些序列資料拆分為單獨的行。
df = pd.DataFrame({
"employee_id": [1, 2, 3],
"first_name": ["John", "Jane", "Joe"],
"direct_reports": [[2, 3], [], []]
})
exploded_df = df.explode("direct_reports")
print(exploded_df)
圖表翻譯:
此圖表展示了使用 pd.DataFrame.explode 將包含列表的列拆分為多行的過程。原始資料中,員工的直接下屬被表示為列表,透過 explode 操作,每個下屬被分配到單獨的一行。
內容解密:
explode("direct_reports")將direct_reports列中的列表元素拆分為單獨的行。- 如果某行的列表為空,則該行在結果 DataFrame 中仍然保留,但對應的
direct_reports值為 NaN。
輸出結果如下:
employee_id first_name direct_reports
0 1 John 2
0 1 John 3
1 2 Jane NaN
2 3 Joe NaN