首页 > 解决方案 > 给定两个具有分组项目的数据框和另一个具有等效组的数据框,我可以创建一个包含来自匹配组的所有单元对的数据框吗?

问题描述

假设我有一个数据框df1

   df1_unit   base_unit
0     x         x
1     y         x
2     z         z
3     t         z
4     u         z

另一个叫df2

   df2_unit   base_unit
0     a         b
1     b         b
2     c         c
3     d         e
4     e         e

还有另一个df_eq给出组之间等价的数据框:

   df1_unit   df2_unit
0     x         b
1     z         e

在 的情况下df1base_unit基本上df1_unit是充当组中所有单元的父单元的 。iex是将x, y,z单元标识为一个组的基本单元。同样对于df2

我正在尝试生成一个数据框,其中包含来自等效组的所有可能的项目对,但没有数据框中的对df_eq(这是我们施加的限制)。在这种情况下,不受限制的输出将是:

   df1_unit   df2_unit
0     x         a
1     x         b       (shouldn't be included)
2     y         a
3     y         b
4     z         d
5     z         e       (shouldn't be included)
6     t         d
7     t         e
8     u         d
9     u         e

并且所需的受限输出将是

   df1_unit   df2_unit
0     x         a
1     y         a
2     y         b
3     z         d
4     t         d
5     t         e
6     u         d
7     u         e

如果不采用荒谬的蛮力方法,我什至难以生成不受限制的输出。有没有一种有效的方法来实现所需的输出?

编辑:我使用以下代码取得了一些进展:

temp = dfeq.rename(columns={'df2u':'base_unit'}).merge(df2, on='base_unit', how='left')
temp = temp[['df1u', 'df2u']]
out = temp.rename(columns={'df1u':'base_unit'}).merge(df1, on='base_unit', how='left')
out = out[['df1u', 'df2u']]

这看起来正确吗?另外,我不确定如何删除out也存在于dfeq.

标签: pythonpandasdataframe

解决方案


您可以使用以下方法:

  1. 我们将映射base_unit中的列df1,同时考虑 中的数据df_eq,因为我们将使用to_dict(orient='split')它来构建一个字典,该字典将被map方法使用。

    map_base_unit_df2 = dict(df_eq.to_dict(orient='split')['data']) 
    df1['base_unit'] = df1['base_unit'].map(map_base_unit_df2)
    
  2. 我们将df_unrestricted使用pd.merge仅选择对我们重要的列来构建。

    df_unrestricted = pd.merge(df1, df2, on='base_unit')[['df1_unit', 'df2_unit']]
    
  3. 最后,添加最后的限制,我的意思是,我们将删除存在的记录,df_eq使用pd.merge++drop_duplicates(keep=False)reset_index(drop=True)

    df_output = pd.concat([df_unrestricted, df_eq]).drop_duplicates(keep=False).reset_index(drop=True)
    

完整代码:

map_base_unit_df2 = dict(df_eq.to_dict(orient='split')['data']) 
df1['base_unit'] = df1['base_unit'].map(map_base_unit_df2)
df_unrestricted = pd.merge(df1, df2, on='base_unit')[['df1_unit', 'df2_unit']]
df_output = pd.concat([df_unrestricted, df_eq]).drop_duplicates(keep=False).reset_index(drop=True)
print(df_output)

输出:

   df1_unit df2_unit
0      x       a
1      y       a
2      y       b
3      z       d
4      t       d
5      t       e
6      u       d
7      u       e

推荐阅读