如何合并轴结构不同的两个Pandas DataFrame数据?
如何合并宽格式月度DataFrame与长格式时序DataFrame?
看起来你已经明确了需求,但用apply加一堆if判断的方式不仅繁琐,处理大数据量时效率也不高。其实我们可以利用Pandas的数据重塑和合并功能,更优雅地解决这个问题,而且性能更好。
核心思路
你的第一个DataFrame是宽格式(每个月份作为一列),第二个是长格式(每行对应一个ID+月度组合)。我们只需要先把宽格式的DataFrame转成长格式,让两者的ID和Month字段对齐,再用合并操作把数据拼起来就行。
具体步骤与代码
1. 定义月份名称到数字的映射
首先我们需要把Jan/Feb这类月份名称转换成df2里的数字(1/2...),这样才能匹配:
month_name_to_num = { 'Jan': 1, 'Feb': 2, 'Mar': 3, 'Apr': 4, 'May': 5, 'Jun': 6, 'Jul': 7, 'Aug': 8, 'Sep': 9, 'Oct': 10, 'Nov': 11, 'Dec': 12 }
2. 将宽格式的df1转成长格式
用melt方法把df1的月度列“拆”成行,同时添加数字月份列:
# 重塑df1:ID作为保留列,其他月度列转成Month_Name和对应值 df1_long = df1.melt(id_vars='ID', var_name='Month_Name', value_name='DF1') # 把月份名称转成数字,和df2的Month字段匹配 df1_long['Month'] = df1_long['Month_Name'].map(month_name_to_num) # 去掉不需要的Month_Name列,只保留ID、Month、DF1 df1_long = df1_long[['ID', 'Month', 'DF1']]
3. 合并两个DataFrame
现在df1_long和df2的结构已经对齐了,直接用pd.merge基于ID和Month两个键合并即可:
merged_df = pd.merge(df2, df1_long, on=['ID', 'Month'], how='left')
这里用how='left'是为了保留df2的所有行,如果你的数据是完全匹配的,用inner也没问题。
完整可复用函数
把上面的步骤封装成函数,方便调用:
import pandas as pd def merge_monthly_data(df1, df2): # 定义月份映射 month_map = { 'Jan': 1, 'Feb': 2, 'Mar': 3, 'Apr': 4, 'May': 5, 'Jun': 6, 'Jul': 7, 'Aug': 8, 'Sep': 9, 'Oct': 10, 'Nov': 11, 'Dec': 12 } # 重塑df1为长格式 df1_long = df1.melt(id_vars='ID', var_name='Month_Name', value_name='DF1') df1_long['Month'] = df1_long['Month_Name'].map(month_map) df1_long = df1_long.drop('Month_Name', axis=1) # 合并数据 return pd.merge(df2, df1_long, on=['ID', 'Month'], how='left')
测试示例
用你给出的样例数据测试一下:
# 示例df1 df1 = pd.DataFrame({ 'ID': [1, 2], 'Jan': ['valJ1', 'valJ2'], 'Feb': ['valF1', 'valF2'], 'Mar': ['valM1', 'valM2'], 'Apr': ['valA1', 'valA2'] }) # 示例df2 df2 = pd.DataFrame({ 'Month': [1,2,3,4,1,2,3,4], 'ID': [1,1,1,1,2,2,2,2], 'data1': ['num']*8, 'data2': ['num']*8 }) # 合并 result = merge_monthly_data(df1, df2) print(result)
输出结果完全符合你的需求:
Month ID data1 data2 DF1 0 1 1 num num valJ1 1 2 1 num num valF1 2 3 1 num num valM1 3 4 1 num num valA1 4 1 2 num num valJ2 5 2 2 num num valF2 6 3 2 num num valM2 7 4 2 num num valA2
为什么不用你原来的apply方法?
apply是逐行处理数据,当你的DataFrame行数很多时,速度会非常慢。而melt和merge都是Pandas的向量化操作,效率要高得多,同时代码更简洁,不容易因为漏写某个月份的if判断而出错。
内容的提问来源于stack exchange,提问作者trpmgo3
相关产品推荐
相关产品推荐

