【问题标题】:How to pivot a dataframe to a wide format?如何将数据框转换为宽格式?
【发布时间】:2020-09-15 14:08:55
【问题描述】:

假设我有一个这样的 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

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

【问题讨论】:

标签: python pandas pivot pivot-table


【解决方案1】:
  • Pivot 无法按预期工作,因为 data 中的值具有唯一索引。
  • 为了让数据透视正确关联值,组必须共享一个索引。
  • 在这种情况下,行可以按 4 分组,并且是有序的,因此我们可以创建一个新索引,并正确旋转 data
  • 这使用assignment expression:=,并且仅在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

【讨论】:

    【解决方案2】:

    一种选择是旋转列以获得新数据框的不同列,然后消除每一列的 NaN 值,最后使用 pandas.concat 函数将它们组合:

    import pandas as pd
    
    data = pd.DataFrame({'header': ["age" , "height" ,  "weight" , "bank_id",  "country", "age" , "height" ,  "weight" , "bank_id", "country", "age" , "height" ,  "weight" ,  "country" ],
                         'values': [   "1",    "6 ft",    "10 kg",        "",    "India",   "2" ,   "5 ft" ,   "20 kg" ,    "A123",        "",   "3" , "5.5 ft" ,   "30 kg" ,    "Japan" ]})
    
    pvt_data = data.pivot( columns='header', values='values' )
    ls_col = list(pvt_data.columns)
    
    ls_cols = []
    for col in ls_col:     
        ls_cols.append(pvt_data[col].dropna().reset_index(drop=True, inplace=False))
    
    print( pd.concat([ls_cols[0],ls_cols[1],ls_cols[2],ls_cols[3],ls_cols[4]],axis=1) )
    
          age bank_id country  height weight
        0   1           India    6 ft  10 kg
        1   2    A123            5 ft  20 kg
        2   3     NaN   Japan  5.5 ft  30 kg
    

    【讨论】:

      猜你喜欢
      • 2019-08-14
      • 1970-01-01
      • 1970-01-01
      • 2023-02-14
      • 2023-02-06
      • 2020-05-28
      • 1970-01-01
      • 2023-02-25
      • 1970-01-01
      相关资源
      最近更新 更多