在上一篇中,我們學會了如何用 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」。
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 或是重複的幽靈數據。下一篇,我們將化身「資料品質守門員」,教你如何優雅地處理這些髒資料!

沒有留言:
張貼留言