如何在Pandas中基于退货表为订单表新增状态标记列?
问题修正:判断订单是否已退货并标记
问题背景
有两个超市销售相关的DataFrame:df_orders(订单数据)和df_returns(退货数据),两者都包含Order ID列,且df_returns行数少于df_orders。需要在df_orders中新增一列,规则为:若订单ID存在于df_returns中则标记为Returned,否则标记为Not returned。
用户尝试的代码运行后所有订单都显示Not returned,但实际存在匹配的订单ID,需修正代码。
示例数据:
import pandas as pd import numpy as np # 示例订单数据 df_order_dict = {'City':['Prior Lake','Chicago','NY','Prior Lake', 'Round Rock'], 'Order ID':[86838 ,90154,15000,10000, 12447]} # 示例退货数据 df_return_dict = {'Order ID':[90154, 86838 ], 'Returned':['Returned', 'Returned']} df_orders = pd.DataFrame.from_dict(df_order_dict) df_returns = pd.DataFrame.from_dict(df_return_dict)
用户尝试的错误代码:
excel_path = r'C:\Users\Korisnik\Desktop\PythonFiles\Omega\SuperStoreUS.xlsx' df = pd.read_excel(excel_path, sheet_name=None) df_order = df.get('Orders') df_returns = df.get('Returns') df_users = df.get('Users') df_n.reset_index(drop=True) df_returns.reset_index(drop=True) df_n['Status'] = np.where( df_n['Order ID'].equals(df_returns['Order ID']) and df_returns["Status"] == "Returned", "Returned", "Not returned")
错误原因
- 逻辑错误:
df_n['Order ID'].equals(df_returns['Order ID'])是判断整列数据是否完全一致,而非逐个订单ID是否存在于退货列表中,和需求完全不符。 - 变量名错误:代码中使用了未定义的
df_n,应为df_order。 - 冗余操作:
reset_index(drop=True)未赋值回原变量,属于无效代码。
正确解决方案
方法1:使用isin()(推荐,简洁高效)
先提取df_returns中的所有退货订单ID,再用isin()判断每个订单是否在退货列表中,最后用np.where生成标记列。
针对示例数据的代码:
# 提取退货订单ID列表 returned_order_ids = df_returns['Order ID'] # 新增Status列 df_orders['Status'] = np.where(df_orders['Order ID'].isin(returned_order_ids), 'Returned', 'Not returned')
针对用户实际Excel数据的修正代码:
import pandas as pd import numpy as np excel_path = r'C:\Users\Korisnik\Desktop\PythonFiles\Omega\SuperStoreUS.xlsx' # 读取所有sheet df_sheets = pd.read_excel(excel_path, sheet_name=None) df_order = df_sheets.get('Orders') df_returns = df_sheets.get('Returns') # 提取退货订单ID returned_ids = df_returns['Order ID'] # 生成标记列 df_order['Status'] = np.where(df_order['Order ID'].isin(returned_ids), 'Returned', 'Not returned')
方法2:使用merge左连接
通过左连接将退货数据合并到订单数据中,再根据合并结果填充标记。
示例代码:
# 左连接订单和退货数据,只保留Order ID和合并标记 merged_df = df_orders.merge(df_returns[['Order ID']], on='Order ID', how='left', indicator=True) # 根据_merge列判断是否存在退货记录 df_orders['Status'] = merged_df['_merge'].map({'both':'Returned', 'left_only':'Not returned'})
验证结果
运行正确代码后,示例df_orders的Status列结果为:
| City | Order ID | Status |
|---|---|---|
| Prior Lake | 86838 | Returned |
| Chicago | 90154 | Returned |
| NY | 15000 | Not returned |
| Prior Lake | 10000 | Not returned |
| Round Rock | 12447 | Not returned |
内容的提问来源于stack exchange,提问作者Aleksandra Milicevic
相关产品推荐
相关产品推荐

