熊猫DataFrame枢轴(重塑形状?)

时间:2020-09-17 00:57:41

标签: python pandas dataframe pivot reshape

我似乎无法正确地做到这一点...这是我想做的事情:

import pandas as pd

df = pd.DataFrame({
    'item_id': [1,1,3,3,3],
    'contributor_id': [1,2,1,4,5],
    'contributor_role': ['sing', 'laugh', 'laugh', 'sing', 'sing'],
    'metric_1': [80, 90, 100, 92, 50],
    'metric_2': [180, 190, 200, 192, 150]
})

--->

   item_id contributor_id contributor_role   metric_1  metric_2  
0     1          1             sing              80       180  
1     1          2             laugh             90       190  
2     3          1             laugh             100      200  
3     3          4             sing              92       192  
4     3          5             sing              50       150  

我想将其重塑为:

     item_id        SING_1_contributor_id SING_1_metric_1 SING_1_metric_2  SING_2_contributor_id SING_2_metric_1 SING_2_metric_2 ... LAUGH_1_contributor_id LAUGH_1_metric_1 LAUGH_1_metric_2 ... <LAUGH_2_...>

0       1               1                 80              180                   N/A                N/A              N/A      ...          2                    90           190 ... N/A..

1       3               4                 92              192                   5                  50               150      ...          1                    100          200 ... N/A..

基本上,对于每个item_id,我都希望将所有相关数据收集到一行中。每个项目可能有多种类型的贡献者,每种类型都有一个最大值(例如,每个项目的最大SING贡献者= A,每个项目的最大LAUGH贡献者= B)。每个贡献者都有一组度量标准(但是对于同一贡献者,不同项目/贡献者类型的值可能不同)。

我可能可以通过一些看似低效的方法(例如,循环和匹配然后填充模板df)来实现这一目标,但是我想知道是否存在更有效的方法,可能是通过巧妙地指定index / values / columns进行数据透视操作(或其他任何方法)。

提前感谢您的任何建议!

编辑:

最终将下面的Ben脚本修改为以下内容:

df['role_count'] = df.groupby(['item_id', 'contributor_role']).cumcount().add(1).astype(str)
df['contributor_role'] = df.apply(lambda row: row['contributor_role'] + '_' + row['role_count'], axis=1)
df = df.set_index(['item_id','contributor_role']).unstack()
df.columns = ['_'.join(x) for x in df.columns.values]

1 个答案:

答案 0 :(得分:2)

您可以使用cumcount创建附加密钥,然后执行unstack

df['newkey']=df.groupby('item_id').cumcount().add(1).astype(str)
df['contributor_id']=df['contributor_id'].astype(str)
s = df.set_index(['item_id','newkey']).unstack().sort_index(level=1,axis=1)
s.columns=s.columns.map('_'.join)
s
Out[38]: 
        contributor_id_1 contributor_role_1  ...  metric_1_3  metric_2_3
item_id                                      ...                        
1                      1               sing  ...         NaN         NaN
3                      1         messaround  ...        50.0       150.0