我有一个带有多索引的数据框,这样我就可以轻松地创建一个使用来自mutliple列的数据作为输入的函数:
df = pd.DataFrame({('ALSN','VA.M'):range(5), ('ALSN','VB.M'):np.arange(5)+2,
('ALVY','VA.M'):range(5), ('ALVY','VB.M'):np.arange(5)+20,
('ALSN', 'VP.M'):np.arange(5)-10, ('ALVY','VP.M'):np.arange(5)-30,
('ALGG', 'VP.M'):np.arange(5)/5.})
ALGG ALSN ALVY
VP.M VA.M VB.M VP.M VA.M VB.M VP.M
0 0.0 0 2 -10 0 20 -30
1 0.2 1 3 -9 1 21 -29
2 0.4 2 4 -8 2 22 -28
3 0.6 3 5 -7 3 23 -27
4 0.8 4 6 -6 4 24 -26
我想过滤这个,然后将一个函数应用到VA.M和VB.M列:
df2 = g.filter(lambda z: z.name[-1] != 'G')
df2.groupby(level=0, axis=1).apply(lambda g: pd.Series(g[g.name]['VB.M']+g[g.name]['VA.M']))
ALSN ALVY
0 2 20
1 4 22
2 6 24
3 8 26
4 10 28
所以,非常好。 但是,我真正想要做的是构建一个函数,该函数将多列作为输入(如上所述),但随后输出多列。因此,例如,它可以将VA.M和VB.M列相加,然后将平方根和立方根作为新列返回。
显然,我可以使用两个不同的应用函数(计算总和,然后是方形或立方根),但我只想执行一次中间步骤(计算总和)。这可能吗?
此外,我希望将输出存储回数据框中,例如列(' ALSN',' V2')和(&# 39; ALSN' V3和#39;)这可以在申请的同时完成吗?或者我是否需要计算V2或V3列,然后获取结果数据帧并与原始数据合并?
答案 0 :(得分:1)
这并不容易。
首先使用get_level_values
按boolean indexing
找到第一级MultiIndex
的值,然后按slicers选择:
lvl = df.columns.get_level_values(0).unique()
lvl = lvl[~lvl.str.contains('G')]
print (lvl)
Index(['ALSN', 'ALVY'], dtype='object')
idx = pd.IndexSlice
df2 = df.loc[:, idx[lvl, ['VA.M','VB.M']]]
print (df2)
ALSN ALVY
VA.M VB.M VA.M VB.M
0 0 2 0 20
1 1 3 1 21
2 2 4 2 22
3 3 5 3 23
4 4 6 4 24
对每个功能使用groupby
,然后concat
使用unstack
:
print (pd.concat([df2.groupby(level=0, axis=1).apply(lambda x: (x**2).sum(axis=1)),
df2.groupby(level=0, axis=1).apply(lambda x: (x**3).sum(axis=1))],
keys=('x^2','x^3')).unstack(0))
ALSN ALVY
x^2 x^3 x^2 x^3
0 4 8 400 8000
1 10 28 442 9262
2 20 72 488 10656
3 34 152 538 12194
4 52 280 592 13888
另一个非常类似的解决方案:
print (df2.groupby(level=0, axis=1).apply(lambda x: (x**2)))
ALSN ALVY
VA.M VB.M VA.M VB.M
0 0 4 0 400
1 1 9 1 441
2 4 16 4 484
3 9 25 9 529
4 16 36 16 576
print (df2.groupby(level=0, axis=1).apply(lambda x: (x**3)))
ALSN ALVY
VA.M VB.M VA.M VB.M
0 0 8 0 8000
1 1 27 1 9261
2 8 64 8 10648
3 27 125 27 12167
4 64 216 64 13824
df21 = df2.groupby(level=0, axis=1).apply(lambda x: (x**2).sum(axis=1))
df22 = df2.groupby(level=0, axis=1).apply(lambda x: (x**3).sum(axis=1))
print (df21)
ALSN ALVY
0 4 400
1 10 442
2 20 488
3 34 538
4 52 592
print (df22)
ALSN ALVY
0 8 8000
1 28 9262
2 72 10656
3 152 12194
4 280 13888
print (pd.concat([df21,df22], keys=('x^2','x^3')).unstack(0))
ALSN ALVY
x^2 x^3 x^2 x^3
0 4 8 400 8000
1 10 28 442 9262
2 20 72 488 10656
3 34 152 538 12194
4 52 280 592 13888
通过评论编辑:
df = df2.groupby(level=0, axis=1).sum()
print (df)
ALSN ALVY
0 2 20
1 4 22
2 6 24
3 8 26
4 10 28
df3 = pd.concat([df ** 2, df ** 3], keys=('x^2','x^3'), axis=1)
df3.columns = df3.columns.swaplevel(0,1)
df3 = df3.sort_index(axis=1)
print (df3)
ALSN ALVY
x^2 x^3 x^2 x^3
0 4 8 400 8000
1 16 64 484 10648
2 36 216 576 13824
3 64 512 676 17576
4 100 1000 784 21952