如何在Python中基于Date和列名匹配合并两个DataFrame?
Python合并两个DataFrame实现指定结构结果
我需要在Python中合并两个DataFrame生成第三个DataFrame。现有两个DataFrame如下:
df1
| Date | A | B | C |
|---|---|---|---|
| 27/04/2023 00:00 | 55.6637 | 0.32194 | 0.145006 |
| 28/04/2023 00:00 | 57.1432 | 0.327949 | 0.14712 |
| 29/04/2023 00:00 | 57.3842 | 0.322167 | 0.146119 |
| 30/04/2023 00:00 | 57.1259 | 0.320318 | 0.145881 |
df2
| Date | change | Ticker |
|---|---|---|
| 27/04/2023 00:00 | 0.1 | A |
| 28/04/2023 00:00 | -0.1 | A |
| 29/04/2023 00:00 | 0.2 | A |
| 30/04/2023 00:00 | -0.2 | A |
| 27/04/2023 00:00 | 0.3 | B |
| 28/04/2023 00:00 | -0.3 | B |
| 29/04/2023 00:00 | 0.4 | B |
| 30/04/2023 00:00 | -0.4 | B |
| 27/04/2023 00:00 | 0.5 | C |
| 28/04/2023 00:00 | -0.5 | C |
| 29/04/2023 00:00 | 0.6 | C |
| 30/04/2023 00:00 | -0.6 | C |
需求:基于Date列匹配两个DataFrame,同时让df2的Ticker值对应df1的列名,生成目标结构的结果DataFrame。之前尝试用.iloc[]未实现需求。
解决方案
.iloc[]是基于位置的索引,无法直接关联Ticker列与df1的列名,正确思路是先转换df1的格式,让两者结构对齐后再合并。
步骤1:将df1从宽格式转窄格式
用pd.melt()把df1的A/B/C列转为Ticker列,对应值存入新列:
import pandas as pd # 假设df1和df2已加载完成 melted_df1 = df1.melt(id_vars='Date', var_name='Ticker', value_name='value')
转换后melted_df1的结构:
| Date | Ticker | value |
|---|---|---|
| 27/04/2023 00:00 | A | 55.6637 |
| 28/04/2023 00:00 | A | 57.1432 |
| ... | ... | ... |
| 30/04/2023 00:00 | C | 0.145881 |
步骤2:合并两个DataFrame
通过Date和Ticker两列匹配合并:
result_df = pd.merge(melted_df1, df2, on=['Date', 'Ticker'], how='inner')
how='inner'保留两边都匹配的记录,可根据需求换成left/right/outer。
步骤3:按需转回宽格式(可选)
如果需要回到类似df1的宽格式,每个日期一行,包含各Ticker的value和change:
# 转宽格式 result_wide = result_df.pivot(index='Date', columns='Ticker', values=['value', 'change']) # 调整列名格式 result_wide.columns = [f'{col[1]}_{col[0]}' for col in result_wide.columns] result_wide = result_wide.reset_index()
最终宽格式示例:
| Date | A_value | A_change | B_value | B_change | C_value | C_change |
|---|---|---|---|---|---|---|
| 27/04/2023 00:00 | 55.6637 | 0.1 | 0.32194 | 0.3 | 0.145006 | 0.5 |
| 28/04/2023 00:00 | 57.1432 | -0.1 | 0.327949 | -0.3 | 0.14712 | -0.5 |
| ... | ... | ... | ... | ... | ... | ... |
完整代码示例
import pandas as pd # 构造示例df1 df1_data = { 'Date': ['27/04/2023 00:00', '28/04/2023 00:00', '29/04/2023 00:00', '30/04/2023 00:00'], 'A': [55.6637, 57.1432, 57.3842, 57.1259], 'B': [0.32194, 0.327949, 0.322167, 0.320318], 'C': [0.145006, 0.14712, 0.146119, 0.145881] } df1 = pd.DataFrame(df1_data) # 构造示例df2 df2_data = { 'Date': ['27/04/2023 00:00']*3 + ['28/04/2023 00:00']*3 + ['29/04/2023 00:00']*3 + ['30/04/2023 00:00']*3, 'change': [0.1, 0.3, 0.5, -0.1, -0.3, -0.5, 0.2, 0.4, 0.6, -0.2, -0.4, -0.6], 'Ticker': ['A', 'B', 'C']*4 } df2 = pd.DataFrame(df2_data) # 转换df1格式 melted_df1 = df1.melt(id_vars='Date', var_name='Ticker', value_name='value') # 合并DataFrame result_df = pd.merge(melted_df1, df2, on=['Date', 'Ticker'], how='inner') # 可选:转回宽格式 result_wide = result_df.pivot(index='Date', columns='Ticker', values=['value', 'change']) result_wide.columns = [f'{col[1]}_{col[0]}' for col in result_wide.columns] result_wide = result_wide.reset_index() print("窄格式结果:") print(result_df.head()) print("\n宽格式结果:") print(result_wide)
内容的提问来源于stack exchange,提问作者user24825361
相关产品推荐
相关产品推荐

