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

时间:2016-12-20 06:52:00

标签: python pandas dataframe reshape

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

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

表1。

因此每个小组(A / B / C)将有3个实体,保证。 并且每个实体都有相应的值(如果不存在则有时为NaN)。

我想将现有格式的数据重新整形为......:

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

表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')

但据我所知,这个问题是生成的重新整形数据透视表中实体的列将不会采用我在上面表2中所希望的格式 - 这对于某些下游内容我很重要处理数据。

我可能会问一个愚蠢的问题,但我很难找到使用现有的枢轴/融合功能的方法,从上面描述的方式从长到宽。任何人都可以帮助我吗?

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

1 个答案:

答案 0 :(得分:3)

您可以使用pivot,新列是indexing with str提取的列entity_id的最后一个值:

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

groupbyapply的另一个解决方案,最后由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