You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何合并轴结构不同的两个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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 18:22:28