在資料處理中,我們經常需要將一列資料擴展為多列。
本教學將介紹如何使用 extend()
方法實現這個功能,
避免使用複雜的列表推導式。
問題描述
假設我們有一個簡單的商品 DataFrame,包含以下欄位:
id
:商品 IDname
:商品名稱count
:商品數量
我們希望根據 count
欄位的值,
將每一列擴展為多列,每列代表一個商品實例。
步驟 1:準備資料
import pandas as pd
from typing import List
# 創建一個簡單的示例 DataFrame
data = {
"id": [1, 2],
"name": ["apple", "banana"],
"count": [2, 3]
}
df = pd.DataFrame(data)
print("原始 DataFrame:")
print(df)
print("\n")
輸出結果:
步驟 2:定義列擴展函數
def expand_row(row: pd.Series) -> List[pd.Series]:
"""
將一列擴展為多列
Args:
row: 一個 pandas Series,代表 DataFrame 中的一列
Returns:
List[pd.Series]: 擴展後的列列表
"""
# 獲取當前列的值
id_val = row["id"]
name_val = row["name"]
count_val = row["count"]
# 創建擴展列列表
expanded_rows: List[pd.Series] = []
# 根據 count 值決定要創建多少列
for i in range(count_val):
# 複製原始列
new_row = row.copy()
# 添加新欄位
new_row["instance"] = i + 1
new_row["new_name"] = f"{name_val}_{i+1}"
# 將新列添加到擴展列列表
expanded_rows.append(new_row)
return expanded_rows
取df 中其中一row的資料(pd.Series)
放進去expand_row(row)
效果:
輸入 1 row (pd.Series)進去expand_row()
輸出List[pd.Series],長度2
1 row 被複製為新的2 rows,裝在list中
步驟 3:使用 extend() 擴展整個 DataFrame
def expand_df(df: pd.DataFrame) -> pd.DataFrame:
"""
擴展整個 DataFrame
Args:
df: 原始 DataFrame
Returns:
pd.DataFrame: 擴展後的 DataFrame
"""
# 創建一個空列表來存儲所有擴展後的列
flat_rows: List[pd.Series] = []
# 遍歷 DataFrame 的每一列
for _, row in df.iterrows():
# 對每一列應用 expand_row 函數,得到擴展的列列表
expanded_rows = expand_row(row)
# 使用 extend 將擴展的列添加到平展列表中
flat_rows.extend(expanded_rows)
# 從平展的列列表創建新的 DataFrame
return pd.DataFrame(flat_rows)
# 使用擴展函數
result_df = expand_df(df)
print("擴展後的 DataFrame:")
print(result_df)
輸出結果:
解析擴展過程
讓我們分解 expand_df
函數中發生的事情:
- 首先,我們創建一個空列表
flat_rows
來存儲所有擴展後的列。 - 然後,我們遍歷原始 DataFrame 的每一列。
- 對於每一列,我們調用
expand_row
函數,
該函數返回一個包含多個row (Series)的列表。 - 使用
extend
方法,我們將這個列表中的所有列添加到flat_rows
中。 - 最後,我們從
flat_rows
創建一個新的 DataFrame。
優點
使用 extend()
進行列擴展有以下優點:
- 更加直觀:程式碼清晰表達了「將多個列添加到結果列表」的意圖。
- 避免嵌套結構:不需要先創建嵌套列表再平展,直接將結果添加到單一列表。
- 更高效:減少了中間資料結構的創建,節省記憶體。
這種方法適用於各種需要根據某些條件或規則
將一列資料擴展為多列的場景,
例如時間序列展開、網路信號名稱擴展等。
Python: List[ pandas.Series ] 轉DataFrame技巧
推薦hahow線上學習python: https://igrape.net/30afN