首页 > 解决方案 > 如何将数据框转换为宽格式?

问题描述

假设我有一个这样的 pandas DataFrame:

import pandas as pd

data = pd.DataFrame({'header': ['age', 'height', 'weight', 'country', 'age', 'height', 'weight', 'bank_id', 'age', 'height', 'weight', 'country'],
                     'values': ['1', '6 ft', '10 kg', 'India', '2', '5 ft', '20 kg', 'A123', '3', '5.5 ft', '30 kg', 'Japan']})

# display(data)
     header  values
0       age       1
1    height    6 ft
2    weight   10 kg
3   country   India
4       age       2
5    height    5 ft
6    weight   20 kg
7   bank_id    A123
8       age       3
9    height  5.5 ft
10   weight   30 kg
11  country   Japan

现在我想使用 Python 转置它们,使它们看起来像这样:

在此处输入图像描述

有些行没有数据,它们将保持空白。

我正在尝试使用代码:

data.pivot_table(columns="header",values="values",aggfunc="max")

[out]:
header age bank_id country height weight
values   3    A123   Japan   6 ft  30 kg

但它没有给出正确的结果。它只显示一行。

标签: pythonpandaspivotpivot-table

解决方案


  • Pivot 不能按预期工作,因为其中的值data具有唯一索引。
  • 为了使枢轴正确关联值,组必须共享一个索引。
  • 在这种情况下,行可以按 4 分组,并且是有序的,因此我们可以创建一个新索引,并正确地进行数据透视data
  • 这使用赋值表达式, :=, 并且仅在 python 3.8 中有效。
import pandas as pd

# set up test dataframe
data = pd.DataFrame({'header': ['age', 'height', 'weight', 'country', 'age', 'height', 'weight', 'bank_id', 'age', 'height', 'weight', 'country'],
                     'values': ['1', '6 ft', '10 kg', 'India', '2', '5 ft', '20 kg', 'A123', '3', '5.5 ft', '30 kg', 'Japan']})

# create a unique index; replace 4 with the real group size
# the associated groups in data, must be consecutive
x = 0
data.index = [x := x+1 if i%4 == 0 else x for i, _ in enumerate(data.index)]

# see the indices are matched for each group compared to the OP
    header  values
1      age       1
1   height    6 ft
1   weight   10 kg
1  country   India
2      age       2
2   height    5 ft
2   weight   20 kg
2  bank_id    A123
3      age       3
3   height  5.5 ft
3   weight   30 kg
3  country   Japan

# create a wide dataframe
wide = data.pivot(columns='header', values='values').reset_index(drop=True)

# header is the .name of columns, to make it nothing
wide.columns.name = None
# display(wide)
age bank_id country  height weight
  1     NaN   India    6 ft  10 kg
  2    A123     NaN    5 ft  20 kg
  3     NaN   Japan  5.5 ft  30 kg

推荐阅读