【问题标题】:align two pandas dataframes on values in one column, otherwise insert NA to match row number将两个 pandas 数据框对齐一列中的值,否则插入 NA 以匹配行号
【发布时间】:2021-09-03 17:38:58
【问题描述】:

我有两个 pandas 数据帧(df1、df2),它们的行数和列数不同,每个 df 的特定列中有一些匹配值,需要注意的是 (1)每个df,以及(2)DataFrames中有不同数量的匹配值。

宝贝示例:

df1 = pd.DataFrame({'id1': [1, 1, 1, 2, 2, 3, 3, 3, 3, 4, 6, 6]})
df2 = pd.DataFrame({'id2': [1, 1, 2, 2, 2, 2, 3, 4, 5],
                    'var1': ['B', 'B', 'W', 'W', 'W', 'W', 'H', 'B', 'A']})

我想做的是创建df3,其中df2['id2']与df1['id1']对齐/索引,这样:

  1. 当df2[id2] 与df1[id1] 的匹配较少(或缺失)时,NaN 被添加到 df3[id2]
  2. 如果df1[id1] 存在但与df2[id2] 不匹配,则NaN 添加到df3[id2] 和df3[var1]
  3. 'var1' 用于所有df3[var1] 的情况,其中df1[id1] 和df2[id2] 匹配
  4. 当df2[id2] 的匹配值多于df1[id1](或根本没有匹配)时,将删除行

生成的 DataFrame (df3) 应如下所示(注意 id2 = 5 和 var1 = A 已消失):

id1 id2 var1
1 1 B
1 1 B
1 NaN B
2 2 W
2 2 W
3 3 H
3 NaN H
3 NaN H
3 NaN H
4 4 B
6 NaN NaN
6 NaN NaN

我找不到正确解决此问题的合并/加入/连接/对齐组合。目前,我尝试过的所有操作都按顺序堆叠行,而不在正确的单元格/行中添加 NaN,而是在 df3 的底部添加所有 NaN 值(所以 id1 和 id2 永远不会对齐) .非常感谢任何帮助!

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    您可以先在groupby.cumcount的基础上为id1和id2分配一个辅助列,然后合并。最后ffill的值var1基于组id1

    def helper(data,col): return data.groupby(col).cumcount()
    
    out = df1.assign(k = helper(df1,['id1'])).merge(df2.assign(k = helper(df2,['id2'])),
          left_on=['id1','k'],right_on=['id2','k'] ,how='left').drop('k',1)
    
    out['var1'] = out['id1'].map(dict(df2[['id2','var1']].drop_duplicates().to_numpy()))
    

    或类似但没有分配 HenryEcker 建议:

    out = df1.merge(df2, left_on=['id1', helper(df1, ['id1'])], 
          right_on=['id2', helper(df2, ['id2'])], how='left').drop(columns='key_1')
    
    out['var1'] = out['id1'].map(dict(df2[['id2','var1']].drop_duplicates().to_numpy()))
    

    print(out)
    
        id1  id2 var1
    0     1  1.0    B
    1     1  1.0    B
    2     1  NaN    B
    3     2  2.0    W
    4     2  2.0    W
    5     3  3.0    H
    6     3  NaN    H
    7     3  NaN    H
    8     3  NaN    H
    9     4  4.0    B
    10    6  NaN  NaN
    11    6  NaN  NaN
    

    【讨论】:

    • 很少使用技巧,但 on left_on 和 right_on 可以采取系列。 df1.merge(df2, left_on=['id1', helper(df1, ['id1'])], right_on=['id2', helper(df2, ['id2'])], how='left').drop(columns='key_1') 可以帮助防止复制较大的数据帧。
    • @HenryEcker 非常感谢,我可以在我的解决方案中添加它吗?
    • 哇,漂亮又高效。完美运行。非常感谢。我在这个问题上苦苦挣扎,并不精通“助手”技术。一个很好的解决方案和一个很大的帮助!
    • @user388754 ,很高兴。如果有帮助,请考虑接受答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-11
    • 2016-12-27
    • 1970-01-01
    • 2019-11-16
    • 2018-07-24
    相关资源
    最近更新 更多