本篇文章同步發布於 Python pandas 使用 iterrows 逐一更新資料【Python 處理 Excel #12】
如果更新資料的過程需要插入一些新欄位,而這些新欄位的值依賴於每一列的值,甚至涉及多個條件判斷時,使用 iterrows
方法更新資料會更靈活。這篇文章介紹如何使用 iterrows
方法更新資料。
現在有兩個 Excel 檔案,order.xlsx 有訂單的相關資訊,shipment.xlsx 記錄訂單的出貨記錄。同一筆訂單可能因為客戶需求、生產條件、運輸方式等因素而分批出貨至客戶手上。shipment.xlsx 保留訂單的所有出貨記錄。order.xlsx 沒有出貨相關資訊。
寫文章當下是 2024 年 9 月,本案例的目標是在 order.xlsx 針對每筆訂單加上該訂單在當月 (2024 年 9 月) 出貨的總數量。order.xlsx 和 shipment.xlsx 的具體內容如下:
order_id | product_name |
---|---|
101 | Laptop Pro |
102 | Gaming Desktop |
103 | Ultrabook |
order_id | ship_date | ship_qty |
---|---|---|
101 | 2024/7/5 | 4 |
102 | 2024/7/10 | 2 |
101 | 2024/8/15 | 3 |
103 | 2024/8/20 | 1 |
102 | 2024/9/1 | 5 |
101 | 2024/9/5 | 4 |
102 | 2024/9/10 | 2 |
101 | 2024/9/15 | 1 |
103 | 2024/9/20 | 3 |
102 | 2024/9/25 | 2 |
首先需要讀取 Excel 檔案:
import pandas as pd
from datetime import datetime, timedelta
import calendar
# 讀取 EXCEL 檔案
order_df = pd.read_excel('order.xlsx')
shipment_df = pd.read_excel('shipment.xlsx')
# 轉換 ship_date 為 datetime 類型
shipment_df['ship_date'] = pd.to_datetime(shipment_df['ship_date'])
# 新增欄位
order_df['current_month_ship_qty'] = 0
shipment_df
中的 ship_date
轉換為 datetime 類型,以便後續的日期操作。order_df
中新增一個名稱為 current_month_ship_qty
的欄位,初始值設為 0。接著從 shipment_df
的所有資料中篩選出當月 (2024 年 9 月) 的資料:
# 尋找上個月的最後一天
today = datetime.now()
prev_month_end = today.replace(day=1) - timedelta(days=1)
# 篩選當月資料
current_month_mask = prev_month_end < shipment_df['ship_date']
current_month_shipment_df = shipment_df[current_month_mask].copy()
這個步驟使用 iterrows
方法遍歷訂單資料,並更新每個訂單的當月出貨數量:
# 更新資料
for index, row in order_df.iterrows():
order_id = row['order_id']
mask = current_month_shipment_df['order_id'] == order_id
matching_rows = current_month_shipment_df[mask]
if not matching_rows.empty:
ship_qty = matching_rows['ship_qty'].sum()
order_df.at[index, 'current_month_ship_qty'] = ship_qty
# 顯示更新後的訂單 DataFrame
print(order_df)
iterrows()
遍歷 order_df
中的每一列order_df
中對應的 current_month_ship_qty
值。order_df
查看結果。下方式這個案例的完整程式碼:
import pandas as pd
from datetime import datetime, timedelta
import calendar
# 讀取 EXCEL 檔案
order_df = pd.read_excel('order.xlsx')
shipment_df = pd.read_excel('shipment.xlsx')
# 轉換 ship_date 為 datetime 類型
shipment_df['ship_date'] = pd.to_datetime(shipment_df['ship_date'])
# 新增欄位
order_df['current_month_ship_qty'] = 0
# 尋找上個月的最後一天
today = datetime.now()
prev_month_end = today.replace(day=1) - timedelta(days=1)
# 篩選當月資料
current_month_mask = prev_month_end < shipment_df['ship_date']
current_month_shipment_df = shipment_df[current_month_mask].copy()
# 更新資料
for index, row in order_df.iterrows():
order_id = row['order_id']
mask = current_month_shipment_df['order_id'] == order_id
matching_rows = current_month_shipment_df[mask]
if not matching_rows.empty:
ship_qty = matching_rows['ship_qty'].sum()
order_df.at[index, 'current_month_ship_qty'] = ship_qty
# 顯示更新後的訂單 DataFrame
print(order_df)
iterrow
方法讓使用者得以逐列遍歷 DataFrame。這個方法的優點是類似傳統的 for
迴圈,可以輕鬆訪問修改每一列的資料。缺點是對於大型的 DataFrame,iterrows
方法的執行效率可能較差。對於新增簡單的欄位資料,之前文章介紹過的 apply
方法通常比 iterrows
方法更快。
這篇文章的案例中多次使用遮罩 (mask) 篩選數據。例如:
mask = current_month_shipment_df['order_id'] == order_id
matching_rows = current_month_shipment_df[mask]
遮罩是一個布林值的 Series,與原 DataFrame 的列數相同。當使用者將遮罩應用到 DataFrame 時,只有遮罩中為 True 的列會被保留。
iterrows
方法用於 pandas 逐列處理數據。本篇文章同步發布於 Python pandas 使用 iterrows 逐一更新資料【Python 處理 Excel #12】