我有多个数据框,示例数据:
df1:
user_id username firstname lastname
123 abc abc abc
456 def def def
789 ghi ghi ghi
Run Code Online (Sandbox Code Playgroud)
df2:
user_id username firstname lastname
111 xyz xyz xyz
456 def def def
234 mnp mnp mnp
Run Code Online (Sandbox Code Playgroud)
df3:
user_id username firstname lastname
789 ghi ghi ghi
456 def def def
222 uwv uwv uwv
Run Code Online (Sandbox Code Playgroud)
我想连接这些数据框,删除重复的行,并通过添加更多列来跟踪行的来源。期望的输出:
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
Run Code Online (Sandbox Code Playgroud)
我可以通过使用连接来做第一步:
pd.concat([df1, df2, df3]).drop_duplicates('user_id').reset_index(drop=True)
Run Code Online (Sandbox Code Playgroud)
我该如何做最后一步(制作原点列)?我不知道如何在没有 forloop 的情况下执行此操作,这对于大数据框不实用。谢谢
由于您df's在连接后需要名称的详细信息,因此不应删除它们。
需要将dfname添加为列,以便连接后我们可以知道,哪一行来自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'
Run Code Online (Sandbox Code Playgroud)
现在,使用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()
Run Code Online (Sandbox Code Playgroud)
输出:
>>> 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]
Run Code Online (Sandbox Code Playgroud)
您需要进行一种热编码才能获得预期的结果,例如(从此处引用)
使用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
Run Code Online (Sandbox Code Playgroud)
最后,
>>> 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
Run Code Online (Sandbox Code Playgroud)