为了账号安全,请及时绑定邮箱和手机立即绑定

连接python数据帧,删除重复项并保留行源记录

连接python数据帧,删除重复项并保留行源记录

犯罪嫌疑人X 2022-08-16 18:26:45
我有多个数据帧,示例数据:df1:user_id    username firstname lastname  123         abc      abc       abc 456         def      def       def  789         ghi      ghi       ghidf2:user_id     username  firstname lastname 111         xyz       xyz       xyz 456         def       def       def 234         mnp       mnp       mnpdf3:user_id     username  firstname lastname 789         ghi       ghi       ghi        456         def       def       def 222         uwv       uwv       uwv       我想连接这些数据帧,删除重复的行,并通过添加更多列来跟踪行的来源。所需输出:df1:user_id    username firstname lastname df1 df2 df3 123         abc       abc       abc    1   0   0 456         def       def       def    1   1   1 789         ghi       ghi       ghi    1   0   1 111         xyz       xyz       xyz    0   1   0 234         mnp       mnp       mnp    0   1   0 222         uwv       uwv       uwv    0   0   1      我可以使用以下命令串联执行第一步:pd.concat([df1, df2, df3]).drop_duplicates('user_id').reset_index(drop=True)如何执行最后一步(制作原点列)?我不知道如何在没有forloop的情况下做到这一点,这对于大数据帧是不切实际的。谢谢
查看完整描述

2 回答

?
BIG阳

TA贡献1859条经验 获得超6个赞

由于连接后需要名称的详细信息,因此不应删除它们。df's


您需要将名称添加为列,以便在连接后,我们可以知道哪一行来自哪一行。dfdf


>>> cols = df1.columns.to_list() # Store columns before adding `origin` column to use later in groupby

>>> df1['origin'] = 'df1'

>>> df2['origin'] = 'df2'

>>> df3['origin'] = 'df3'

现在,使用您的任务变得容易。groupby


>>> df = pd.concat([df1, df2, df3])\

    .reset_index(drop=True)\

    .groupby(by = cols, axis=0)\

    .apply(lambda x: x['origin'].values)\

    .to_frame('origin')\

    .reset_index()

输出:


>>> df


   user_id username firstname lastname           origin

0      111      xyz       xyz      xyz            [df2]

1      123      abc       abc      abc            [df1]

2      222      uwv       uwv      uwv            [df3]

3      234      mnp       mnp      mnp            [df2]

4      456      def       def      def  [df1, df2, df3]

5      789      ghi       ghi      ghi       [df1, df3]

您需要执行一个热编码才能获得预期的结果,例如,(从这里引用)


使用sklearn.preprocessing.MultiLabelBinarizer(您也可以使用,请检查这个pd.get_dummies)


>>> from sklearn.preprocessing import MultiLabelBinarizer

>>> mlb = MultiLabelBinarizer()

>>> expandedLabelData = mlb.fit_transform(df["origin"])

>>> labelClasses = mlb.classes_

>>> encoded_df = pd.DataFrame(expandedLabelData, columns=labelClasses)

   df1  df2  df3

0    0    1    0

1    1    0    0

2    0    0    1

3    0    1    0

4    1    1    1

5    1    0    1

最后


>>> pd.concat([df.drop('origin', axis=1), encoded_df], axis=1)

   user_id username firstname lastname  df1  df2  df3

0      111      xyz       xyz      xyz    0    1    0

1      123      abc       abc      abc    1    0    0

2      222      uwv       uwv      uwv    0    0    1

3      234      mnp       mnp      mnp    0    1    0

4      456      def       def      def    1    1    1

5      789      ghi       ghi      ghi    1    0    1


查看完整回答
反对 回复 2022-08-16
?
千巷猫影

TA贡献1829条经验 获得超7个赞

创建 DataFrames 的字典,因此,如果创建了 concat,则通过DataFrame.reset_index将其转换为列,并按所有列进行分组,因此最后可以使用 Series.str.get_dummies:MultiIndexjoinreset_index


dfs = {'df1': df1, 'df2': df2, 'df3': df3}

df = (pd.concat(dfs)

       .reset_index()

       .groupby(df1.columns.tolist())['level_0']

       .apply('|'.join)

       .str.get_dummies()

       .reset_index())

print (df)

   user_id username firstname lastname  df1  df2  df3

0      111      xyz       xyz      xyz    0    1    0

1      123      abc       abc      abc    1    0    0

2      222      uwv       uwv      uwv    0    0    1

3      234      mnp       mnp      mnp    0    1    0

4      456      def       def      def    1    1    1

5      789      ghi       ghi      ghi    1    0    1


查看完整回答
反对 回复 2022-08-16
  • 2 回答
  • 0 关注
  • 62 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信