查找重复行并将相应的数据移动到与原始行相邻的位置

Find duplicate rows and move corresponding data to adjacent to original row

我有以下数据框:

unique_id   person_id   fruit_name  poduct  guest   
92          11          apple       silver  Miller  
93          12          cherry      bronze  Gus     
967         121        orange       purple  Mike    
94          176         apple       silver  Miller  
95          176         banana      gold    John    
96          176         orange      purple  Mike    
445         111         apple       silver  Miller  
100         112         cherry      bronze  Gus     
232         111         apple       silver  Miller  
355         555        cherry       bronze  Gus 

我想抓取在 person_id 列下找到的任何重复值并将它们移动到原始行附近,这是预期输出的示例:

unique_id   person_id   fruit_name  poduct  guest   unique_id_1 fruit_name  poduct  guest unique_id_2   fruit_name  poduct  guest   
92          11          apple       silver  Miller  
93          12          cherry      bronze  Gus     
967         121        orange       purple  Mike    
94          176         apple       silver  Miller  95          banana      gold    John  96             orange     purple  Mike
100         112         cherry      bronze  Gus 
445         111         apple       silver  Miller  232         apple       silver  Miller  
355         555        cherry       bronze  Gus 

我不太确定我应该在线搜索什么才能实现这一点,非常感谢任何建议。

尝试:

# Separate duplicated lines
dup = df.duplicated(subset=['person_id'], keep='last')
rem = df[~dup]

# Merge on "person_id"
new_df = pd.merge(
    right=rem,
    left=dup,
    how="outer",
    on=["person_id"],
    suffixes=("_0", "_1"],
)

这是一个“长到宽”的转变。

您可以添加一列来标识某行属于哪个组。

df['group'] = df.groupby('person_id').cumcount() + 1

>>> df
   unique_id  person_id fruit_name  poduct   guest  group
0         92         11      apple  silver  Miller      1
1         93         12     cherry  bronze     Gus      1
2        967        121     orange  purple    Mike      1
3         94        176      apple  silver  Miller      1
4         95        176     banana    gold    John      2
5         96        176     orange  purple    Mike      3
6        445        111      apple  silver  Miller      1
7        100        112     cherry  bronze     Gus      1
8        232        111      apple  silver  Miller      2
9        355        555     cherry  bronze     Gus      1

然后在 DataFrame.pivot()

中使用
>>> df.pivot(index='person_id', columns='group').sort_index(axis=1, level=1)

          fruit_name   guest  poduct unique_id fruit_name   guest  poduct unique_id fruit_name guest  poduct unique_id
group              1       1       1         1          2       2       2         2          3     3       3         3
person_id                                                                                                             
11             apple  Miller  silver      92.0        NaN     NaN     NaN       NaN        NaN   NaN     NaN       NaN
12            cherry     Gus  bronze      93.0        NaN     NaN     NaN       NaN        NaN   NaN     NaN       NaN
111            apple  Miller  silver     445.0      apple  Miller  silver     232.0        NaN   NaN     NaN       NaN
112           cherry     Gus  bronze     100.0        NaN     NaN     NaN       NaN        NaN   NaN     NaN       NaN
121           orange    Mike  purple     967.0        NaN     NaN     NaN       NaN        NaN   NaN     NaN       NaN
176            apple  Miller  silver      94.0     banana    John    gold      95.0     orange  Mike  purple      96.0
555           cherry     Gus  bronze     355.0        NaN     NaN     NaN       NaN        NaN   NaN     NaN       NaN

然后您可以重命名列。

out = df.pivot(index='person_id', columns='group').sort_index(axis=1, level=1)
out.columns = [ f'{x}_{y}' for x, y in out.columns ]

>>> out.reset_index()
   person_id fruit_name_1 guest_1 poduct_1  unique_id_1 fruit_name_2 guest_2 poduct_2  unique_id_2 fruit_name_3 guest_3 poduct_3  unique_id_3
0         11        apple  Miller   silver         92.0          NaN     NaN      NaN          NaN          NaN     NaN      NaN          NaN
1         12       cherry     Gus   bronze         93.0          NaN     NaN      NaN          NaN          NaN     NaN      NaN          NaN
2        111        apple  Miller   silver        445.0        apple  Miller   silver        232.0          NaN     NaN      NaN          NaN
3        112       cherry     Gus   bronze        100.0          NaN     NaN      NaN          NaN          NaN     NaN      NaN          NaN
4        121       orange    Mike   purple        967.0          NaN     NaN      NaN          NaN          NaN     NaN      NaN          NaN
5        176        apple  Miller   silver         94.0       banana    John     gold         95.0       orange    Mike   purple         96.0
6        555       cherry     Gus   bronze        355.0          NaN     NaN      NaN          NaN          NaN     NaN      NaN          NaN

更新


自定义列顺序示例:

order = ['person_id', 'fruit_name', 'unique_id', 'guest', 'poduct']
out = df.pivot(index='person_id', columns='group')
out = out[sorted(out.columns, key=lambda idx: (idx[1], order.index(idx[0])))]
out.columns = [ f'{x}_{y}' for x, y in out.columns ]

>>> out.reset_index()
   person_id fruit_name_1  unique_id_1 guest_1 poduct_1 fruit_name_2  unique_id_2 guest_2 poduct_2 fruit_name_3  unique_id_3 guest_3 poduct_3
0         11        apple         92.0  Miller   silver          NaN          NaN     NaN      NaN          NaN          NaN     NaN      NaN
1         12       cherry         93.0     Gus   bronze          NaN          NaN     NaN      NaN          NaN          NaN     NaN      NaN
2        111        apple        445.0  Miller   silver        apple        232.0  Miller   silver          NaN          NaN     NaN      NaN
3        112       cherry        100.0     Gus   bronze          NaN          NaN     NaN      NaN          NaN          NaN     NaN      NaN
4        121       orange        967.0    Mike   purple          NaN          NaN     NaN      NaN          NaN          NaN     NaN      NaN
5        176        apple         94.0  Miller   silver       banana         95.0    John     gold       orange         96.0    Mike   purple
6        555       cherry        355.0     Gus   bronze          NaN          NaN     NaN      NaN          NaN          NaN     NaN      NaN