2026年10月31日 星期六

【PySpark 大數據處理 05】資料塑形與運算:新增欄位 (withColumn) 與型態轉換 (Cast)

在上一篇中,我們學會了如何用 select() 與 filter() 剔除不要的資料。但面對留下來的資料,我們往往還需要進行「加工」。在實務的 ETL (Extract, Transform, Load) 流程中,最常見的兩個痛點是:資料型態錯誤(例如系統把價格存成了字串)以及需要計算新指標(例如算出總金額或折扣價)。

今天,我們要來認識 PySpark DataFrame 中最強大的變形金剛:withColumn() 函數!

1. 核心觀念:什麼是 withColumn?

與傳統 SQL 使用 ALTER TABLE 或是 SELECT A, B, A*B AS C 的思維不同,在 PySpark 中,DataFrame 是不可變的 (Immutable)。當我們想要新增或修改欄位時,必須使用 withColumn(欄位名稱, 運算邏輯) 來產生一個「全新的 DataFrame」。

資料塑形:型態轉換與新增欄位 原始 DataFrame Item Price(Str) Qty(Int) Apple "50" 3 .cast() Price * Qty 轉換後的新 DataFrame Item Price(Int) Qty(Int) Total(Int) withColumn Apple 50 3 150 使用 df.withColumn("Price", col("Price").cast("int")) 覆蓋舊欄位並轉換型態 使用 df.withColumn("Total", col("Price") * col("Qty")) 計算並產生新欄位
▲ withColumn() 覆蓋型態與衍生新欄位運作原理

2. 型態轉換:讓字串回歸數字本色 (Cast)

從 CSV 讀取資料時,常會遇到數字被當成字串 (String) 的情況。如果沒有轉換回數字,我們就無法進行加減乘除。這時我們可以使用 cast() 來幫欄位「轉型」。

如果 withColumn() 第一個參數的欄位名稱已經存在於 DataFrame 中,PySpark 就會用新的邏輯「覆蓋」原本的欄位。

from pyspark.sql.functions import col

# 將 "Price" 欄位從字串轉換為整數 (integer)
df_casted = df.withColumn("Price", col("Price").cast("integer"))
# 將 "Discount" 欄位轉換為浮點數 (double / float)
df_casted = df_casted.withColumn("Discount", col("Discount").cast("double"))

df_casted.printSchema() # 檢查轉換後的型態

💡 小技巧: 除了 "integer" 和 "double",常用的型態還有 "string" (字串)、"boolean" (布林值) 與 "timestamp" (時間戳記)。

3. 新增欄位:利用現有數據產生新價值

大數據分析的核心價值,往往來自於我們如何組合現有的指標。如果 withColumn() 的欄位名稱是全新的,PySpark 就會在資料表最後方附加一個新的欄位。

# 計算總金額:單價 (Price) 乘上 數量 (Qty)
df_transformed = df_casted.withColumn(
    "Total_Amount", 
    col("Price") * col("Qty")
)

# 計算折扣後的最終價格
df_transformed = df_transformed.withColumn(
    "Final_Price", 
    col("Total_Amount") * (1 - col("Discount"))
)

df_transformed.show(5)

4. 課後小結

withColumn() 是資料工程師每天都會用到的起手式。學會了「過濾 (Filter)」、「選取 (Select)」與「變形 (withColumn)」後,你已經能處理 80% 的日常數據了!不過,真實資料總是殘酷的,裡面往往藏著空白、Null 或是重複的幽靈數據。下一篇,我們將化身「資料品質守門員」,教你如何優雅地處理這些髒資料!

沒有留言:

張貼留言

熱門文章