如何根据多索引列的第二级中的名称计算表达式

时间:2017-09-05 05:36:43

标签: python pandas

假设我有一个带有multiindex列对象的数据帧,其中第一级定义了某个类别,第二级定义了公式的组件。考虑数据框df

np.random.seed([3,1415])

mux = pd.MultiIndex.from_product([list('XYZ'), list('kap'), ])
df = pd.DataFrame(np.random.randint(1, 5, size=(2, 9)), columns=mux)

df

   X        Y        Z      
   k  a  p  k  a  p  k  a  p
0  1  4  3  4  3  3  4  3  4
1  2  4  2  3  4  4  1  4  3

我想为每个k * a ** pXY

计算公式Z

我可以分配一个单独的数据框

x = df.X

x.eval('k * a ** p')

0    64
1    32
dtype: int64

但是如何同时为XYZ提供此功能。

最终结果如下:

    X    Y    Z
0  64  108  324
1  32  768   64

4 个答案:

答案 0 :(得分:3)

1)。 groupby

的一种方式是level
In [1841]: df.groupby(level=0, axis=1).apply(lambda x: x[x.name].eval('k*a**p'))
Out[1841]:
    X    Y    Z
0  64  108  324
1  32  768   64

2)。另一个,按级别循环。

In [1818]: pd.DataFrame({c: df[c].eval('k*a**p') for c in df.columns.levels[0]})
Out[1818]:
    X    Y    Z
0  64  108  324
1  32  768   64

答案 1 :(得分:2)

没有评估的解决方案:

d = {c: df[c].assign(A=lambda x: x.k*x.a**x.p)['A'] for c in df.columns.levels[0]}
df1 = pd.DataFrame(d)
print (df1)
    X    Y    Z
0  64  108  324
1  32  768   64

答案 2 :(得分:1)

选项1

df.stack(0).eval('k * a ** p').unstack()

    X    Y    Z
0  64  108  324
1  32  768   64

选项2

df.swaplevel(0, 1, 1).pipe(lambda d: d.k * d.a ** d.p)

    X    Y    Z
0  64  108  324
1  32  768   64

答案 3 :(得分:1)

有点难看,但涉及对列进行排序,然后调用.mul.pow

df2 = df.sort_index(level=[0, 1], axis=1)

v = df2.loc[:, (slice(None), 'a')]\
                  .pow(df2.loc[:, (slice(None), 'p')].values, 1)
out = df2.loc[:, (slice(None), 'k')].mul(v.values, 1)

print(out)

    X    Y    Z
    k    k    k
0  64  108  324
1  32  768   64