如何基于另外两个Pandas DataFrame的值为首个DataFrame新增Rate列
解决Pandas DataFrame新增Rate列的问题
需求说明
需要基于df2和df3,为df1新增Rate列:
- 第一步:匹配df1与df2的
Name列,确定员工对应的奖金类型; - 第二步:匹配df1与df3的
Date列,从df3对应列中获取当日费率; - 需处理三个特殊场景:
- df3无常规费率对应列;
- 常规费率固定为3;
- df2的奖金名称与df3列名仅首尾字母一致,中间以连字符连接(如
sales对应s-s,overtime对应o-t)。
解决方案代码
import pandas as pd import numpy as np # 1. 创建示例数据 dates = pd.date_range('20190101', periods=4) df1 = pd.DataFrame(np.array([ [dates[0], 'Tim'], [dates[1], 'Michael'], # 修正拼写,与df2保持一致 [dates[2], 'David'], [dates[3], 'Tim']]), columns=['Date', 'Name']) df2 = pd.DataFrame(np.array([ ['David', 'none'], ['Tim', 'sales'], ['Michael', 'overtime']]), columns=['Name', 'bonus']) df3 = pd.DataFrame(np.array([ [dates[0], 8, 10], [dates[1], 4, 5], [dates[2], 4, 5], [dates[3], 4, 5]]), columns=['Date', 's-s', 'o-t']) # 2. 合并df1与df2,获取员工奖金类型 df_merged = df1.merge(df2, on='Name', how='left') # 3. 根据奖金名称生成df3对应的列名 def get_target_col(bonus): if bonus == 'none': return None # 提取首尾字母,转为小写并以连字符连接 return f"{bonus[0].lower()}-{bonus[-1].lower()}" df_merged['target_col'] = df_merged['bonus'].apply(get_target_col) # 4. 合并df_merged与df3,关联日期对应的费率数据 df_merged = df_merged.merge(df3, on='Date', how='left') # 5. 提取Rate列:匹配到列则取对应值,否则用默认值3 df_merged['Rate'] = df_merged.apply( lambda row: row[row['target_col']] if row['target_col'] is not None else 3, axis=1 ) # 6. 整理得到最终的df1 df1_final = df_merged[['Date', 'Name', 'Rate']] print(df1_final)
代码说明
- 合并匹配:通过两次
merge操作分别关联员工奖金类型和日期费率数据; - 列名映射:自定义函数
get_target_col处理奖金名称与df3列名的匹配规则; - 特殊场景处理:当奖金类型为
none时,直接赋值固定费率3,避免因df3无对应列导致的取值错误。
输出结果
Date Name Rate 0 2019-01-01 Tim 8.0 1 2019-01-02 Michael 5.0 2 2019-01-03 David 3.0 3 2019-01-04 Tim 4.0
内容的提问来源于stack exchange,提问作者Bazman
相关产品推荐
相关产品推荐

