Python Pandas:按标签匹配列将一个DataFrame的值添加到另一个
解决方案:基于PN和Date匹配填充DataFrame值
我明白你要解决的问题——根据PN和Date两个键,把df1里对应的值匹配到df2中,无匹配时填充NaN。其实这个问题用pandas的宽表转长表+左连接就能优雅解决,步骤非常清晰:
步骤1:先构造示例数据(还原你提供的df1和df2结构)
首先我们先把你给出的零散数据转换成可运行的pandas DataFrame:
import pandas as pd # 构造df1(宽格式:日期为列,PN为行) data_df1 = { 'PN': [90020, 90022, 90061, 90065, 90099], '2017-11-01': [105.0, 100.0, -3.0, 30.0, 2.0], '2017-11-02': [105.0, 100.0, -3.0, 30.0, 2.0], '2017-11-03': [105.0, 100.0, -3.0, 30.0, 2.0] } df1 = pd.DataFrame(data_df1) # 构造df2(长格式:PN和Date为匹配键),补全你截断的部分并加入一个无匹配项测试 data_df2 = { 'PN': [90020, 90020, 90022, 90061, 99999], 'Date': ['2017-11-01', '2017-11-02', '2017-11-03', '2017-11-01', '2017-11-01'] } df2 = pd.DataFrame(data_df2)
步骤2:将df1从宽格式转换为长格式
df1当前是宽表(日期作为列名),无法直接和df2的长表结构匹配。我们用melt()函数把它转成PN+Date+Value的长格式:
# 转长表:id_vars保留PN列,把日期列转成Date列,对应数值转成Value列 df1_melted = df1.melt(id_vars='PN', var_name='Date', value_name='Value')
转换后的df1_melted核心结构如下:
| PN | Date | Value | |
|---|---|---|---|
| 0 | 90020 | 2017-11-01 | 105 |
| 1 | 90022 | 2017-11-01 | 100 |
| 2 | 90061 | 2017-11-01 | -3 |
步骤3:左连接合并两个DataFrame
用pd.merge()做左连接,以PN和Date为匹配键,这样会保留df2的所有行,没有匹配的项会自动填充NaN:
# 左连接:保留df2的所有记录,无匹配时Value列填NaN result_df = pd.merge(df2, df1_melted, on=['PN', 'Date'], how='left')
最终结果示例
运行后result_df的输出如下:
| PN | Date | Value | |
|---|---|---|---|
| 0 | 90020 | 2017-11-01 | 105 |
| 1 | 90020 | 2017-11-02 | 105 |
| 2 | 90022 | 2017-11-03 | 100 |
| 3 | 90061 | 2017-11-01 | -3 |
| 4 | 99999 | 2017-11-01 | NaN |
可以看到,最后一行的99999在df1中没有匹配项,Value列自动填充了NaN,完全符合你的需求。
内容的提问来源于stack exchange,提问作者bcal
相关产品推荐
相关产品推荐

