如何基于列值合并Pandas DataFrame生成目标数据集?
实现方法
我来一步步帮你搞定这个合并需求,核心思路是先把df2的长格式数据转成宽格式,再和df1做匹配合并,具体操作如下:
1. 先处理df2:将长格式转为宽格式
df2里的x是布尔类型标记,我们需要把对应的y值拆分成y_x(x为True时的y)和y_notx(x为False时的y)两列。用pandas的pivot方法就能轻松实现:
# 先把df2的索引转成列,命名为'b',方便后续和df1匹配 df2_reset = df2.reset_index(names='b') # 按'b'分组,把'x'的布尔值作为列名,对应填充'y'的值 df2_pivot = df2_reset.pivot(index='b', columns='x', values='y').rename(columns={True: 'y_x', False: 'y_notx'})
处理后的df2_pivot结构如下:
| b | y_x | y_notx |
|---|---|---|
| 3 | 5.4 | 6.9 |
| 4 | 9.8 | NaN |
| 7 | 7.8 | NaN |
| 8 | NaN | 5.6 |
2. 和df1合并得到目标df3
接下来只需要把处理后的df2_pivot和df1按b列做左合并,这样能保留df1里所有的b值,没有匹配到的数据会显示NaN:
df3 = df1.merge(df2_pivot, on='b', how='left')
完整可运行代码
把所有步骤整合起来,完整代码示例如下:
import pandas as pd # 构造你提供的示例数据 df1 = pd.DataFrame({'b': [3,4,7,8,10]}, index=[1,2,3,4,5]) df2 = pd.DataFrame({'x': [True, False, True, True, False], 'y': [5.4,6.9,9.8,7.8,5.6]}, index=[3,3,4,7,8]) # 处理df2为宽格式 df2_reset = df2.reset_index(names='b') df2_pivot = df2_reset.pivot(index='b', columns='x', values='y').rename(columns={True: 'y_x', False: 'y_notx'}) # 合并得到df3 df3 = df1.merge(df2_pivot, on='b', how='left') print(df3)
运行后输出的df3就是你想要的结构:
| b | y_notx | y_x | |
|---|---|---|---|
| 0 | 3 | 6.9 | 5.4 |
| 1 | 4 | NaN | 9.8 |
| 2 | 7 | NaN | 7.8 |
| 3 | 8 | 5.6 | NaN |
| 4 | 10 | NaN | NaN |
补充小贴士
- 如果df2里同一个
b+x组合存在多个重复值,直接用pivot会报错,这时候可以换成pivot_table并指定聚合函数(比如取平均值):
df2_pivot = df2_reset.pivot_table(index='b', columns='x', values='y', aggfunc='mean').rename(columns={True: 'y_x', False: 'y_notx'})
- 选择
how='left'是为了确保df1里的所有行都被保留,如果你只需要保留两边都匹配的行,换成how='inner'即可。
内容的提问来源于stack exchange,提问作者peternator
相关产品推荐
相关产品推荐

