使用分组数据重塑 Pandas 数据框(从长到宽)

Reshaping Pandas Dataframe with Grouped Data (Long to Wide)

假设我有以下格式的数据:

group_id | entity_id | value
    A          a1        5
    A          a2        3
    A          a3        2
    B          b1        10
    B          b2        8
    B          b3        11
    C          c1        2
    C          c2        6
    C          c3        NaN

Table 1.

所以每个组 (A/B/C) 将有 3 个实体,保证。 每个实体都有一个对应的值(如果不存在,有时为 NaN)。

我想将现有格式的数据重塑为...:[=​​14=]

group_id | entity_1 | entity_2 | entity_3
   A          5          3          2
   B          10         8          11
   C          2          6          NaN

Table 2.

其中entity_1/entity_2/entity_3分别对应a1/a2/a3(或b1/b2/b3、c1/c2/c3)。

我该怎么做?

我找到的一个解决方案是使用数据透视函数,所以...

df.pivot(index='group_id', columns='entity_id', values='value')

但据我了解,问题在于生成的重塑枢轴 table 中实体的列将不是我在上面 Table 中想要的格式 2 --这对于我处理数据的一些下游工作很重要。

我可能会问一个愚蠢的问题,但我无法找到使用现有 pivot/melt 函数按照我上面描述的方式从长到宽的方法。谁能帮帮我?

如有必要,我很乐意提供更多详细信息,请告诉我!

您可以使用 pivot and new columns are last value of column entity_id extracted by indexing with str:

df = pd.pivot(index=df.group_id, columns=df.entity_id.str[-1], values=df.value)
       .add_prefix('entity_')
       .rename_axis(None, axis=1)
       .reset_index()
print (df)
  group_id  entity_1  entity_2  entity_3
0        A       5.0       3.0       2.0
1        B      10.0       8.0      11.0
2        C       2.0       6.0       NaN

cumcount的解决方案:

df = pd.pivot(index=df.group_id,
              columns=df.groupby('group_id').cumcount() + 1, 
              values=df.value)
       .add_prefix('entity_')
       .reset_index()
print (df)
  group_id  entity_1  entity_2  entity_3
0        A       5.0       3.0       2.0
1        B      10.0       8.0      11.0
2        C       2.0       6.0       NaN

另一个解决方案groupby and apply, last reshape by unstack

df = df.groupby("group_id")["value"]
       .apply(lambda x: pd.Series(x.values))
       .unstack()
       .add_prefix('entity_')
       .reset_index()
print (df)
  group_id  entity_0  entity_1  entity_2
0        A       5.0       3.0       2.0
1        B      10.0       8.0      11.0
2        C       2.0       6.0       NaN

如果需要从1开始计数:

df = df.groupby("group_id")["value"].apply(lambda x: pd.Series(x.values))
       .unstack()
       .rename(columns = lambda x: x+1)
       .add_prefix('entity_')
       .reset_index()
print (df)
  group_id  entity_1  entity_2  entity_3
0        A       5.0       3.0       2.0
1        B      10.0       8.0      11.0
2        C       2.0       6.0       NaN