如何将panda分组数据分配给多层索引的数据框?

3

目标

我有一个初始数据框,看起来像这样:

   Serial No.  Data One  Data Two
0          01  0.258625  0.667996
1          01  0.192356  0.723055
2          01  0.738066  0.266488
3          01  0.374525  0.059664
4          01  0.193977  0.104213
5          01  0.213749  0.366608
⁞
49         05  0.948550  0.823888

我希望将它重新排列为一个多索引数据框,其中包含数据类型和序列号的列:

Data        Data One                  Data Two                
Serial No.        01  02  03  04  05        01  02  03  04  05

代码

为了生成和填充多级索引数据框,我编写了一小段代码:

serial_numbers = ["01", "02", "03", "04", "05"]
headings = ["Serial No.", "Data One", "Data Two"]
arrays = [[], []]
for ii, heading in enumerate(headings[1:]):
    arrays[0] += [heading]*len(serial_numbers)
    arrays[1] += serial_numbers

index = pd.MultiIndex.from_tuples(list(zip(*arrays)), names=["Data", "Serial No."])

group = random_data.groupby(headings[0])
data = pd.DataFrame(np.zeros((len(group.get_group(serial_numbers[0])), len(index))), columns=index)
for heading in headings[1:]:
    for serial_number in serial_numbers:
        data.loc[:, (heading, serial_number)] = group.get_group(serial_number).loc[:, heading]

问题

以上代码创建了一个数据框,其中每种数据类型的第一个序列号填充了值,其余都是NaN:

Data        Data One                  Data Two                
Serial No.        01  02  03  04  05        01  02  03  04  05
0           0.258625 NaN NaN NaN NaN  0.667996 NaN NaN NaN NaN
1           0.192356 NaN NaN NaN NaN  0.723055 NaN NaN NaN NaN
2           0.738066 NaN NaN NaN NaN  0.266488 NaN NaN NaN NaN
3           0.374525 NaN NaN NaN NaN  0.059664 NaN NaN NaN NaN
4           0.193977 NaN NaN NaN NaN  0.104213 NaN NaN NaN NaN
5           0.213749 NaN NaN NaN NaN  0.366608 NaN NaN NaN NaN
6           0.829126 NaN NaN NaN NaN  0.972882 NaN NaN NaN NaN
7           0.494763 NaN NaN NaN NaN  0.482118 NaN NaN NaN NaN
8           0.024283 NaN NaN NaN NaN  0.538428 NaN NaN NaN NaN
9           0.700613 NaN NaN NaN NaN  0.067831 NaN NaN NaN NaN

附录

为什么这个方法适用于每种数据类型的第一个序列号,而不适用于其他的?

在真实环境中,输入数据通常来自CSV文件和pandas.read_csv函数。但是为了回答这个问题,我使用了numpy生成随机数据以及其他一些代码进行了结构化处理。

serial_no_col = []
for serial_number in serial_numbers:
    for ii in range(10):
        serial_no_col.append(serial_number)
random_data = pd.DataFrame(np.random.rand(50, 3), columns=headings)
random_data.loc[:, "Serial No."] = serial_no_col
1个回答

1

使用 cumcount 处理由 set_index 创建的新索引,然后再进行 unstack 操作:

print (df)
   Serial No.  Data One  Data Two
0          01  0.258625  0.667996
1          01  0.192356  0.723055
2          02  0.738066  0.266488
3          02  0.374525  0.059664
4          03  0.193977  0.104213
5          03  0.213749  0.366608
49         05  0.948550  0.823888

df = df.set_index([df.groupby('Serial No.').cumcount(), 'Serial No.']).unstack()
print (df)
            Data One                               Data Two            \
Serial No.        01        02        03       05        01        02   
0           0.258625  0.738066  0.193977  0.94855  0.667996  0.266488   
1           0.192356  0.374525  0.213749      NaN  0.723055  0.059664   


Serial No.        03        05  
0           0.104213  0.823888  
1           0.366608       NaN  

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接