【问题标题】:Concat python dataframes, drop duplicate and keep record of rows originConcat python数据框,删除重复并保留行源记录
【发布时间】:2020-03-02 04:47:07
【问题描述】:

我有多个数据框,示例数据:

df1:

user_id    username firstname lastname 
 123         abc      abc       abc
 456         def      def       def 
 789         ghi      ghi       ghi

df2:

user_id     username  firstname lastname
 111         xyz       xyz       xyz
 456         def       def       def
 234         mnp       mnp       mnp

df3:

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 的情况下做到这一点,这对于大数据框来说是不实用的。谢谢

【问题讨论】:

    标签: python pandas


    【解决方案1】:

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

    你需要将df的名字添加为一列,这样拼接后我们就可以知道,哪一行来自哪个df

    >>> 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]
    

    您需要进行一次热编码以获得预期的结果,例如(引用自here

    使用sklearn.preprocessing.MultiLabelBinarizer(你也可以使用pd.get_dummies,检查this

    >>> 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
    

    【讨论】:

      【解决方案2】:

      创建DataFrames的字典,所以如果使用concat创建MultiIndex,将其转换为DataFrame.reset_index的列并按join的所有列分组,所以最后可以使用Series.str.get_dummiesreset_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
      

      【讨论】:

        猜你喜欢
        • 2015-09-27
        • 2012-04-12
        • 2019-12-20
        • 2016-12-05
        • 2021-02-19
        • 1970-01-01
        • 2020-10-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多