Pandas 如何像在面板上一样优雅地在多索引数据框上应用函数?
假设我有一个数据帧,如:Pandas 如何像在面板上一样优雅地在多索引数据框上应用函数?,pandas,dataframe,Pandas,Dataframe,假设我有一个数据帧,如: ticker MS AAPL field price volume price volume 0 -0.861210 -0.319607 -0.855145 0.635594 1 -1.986693 -0.526885 -1.765813 1.696533 2 -0.154544 -1.152361 -1.391477 -2.016119 3
ticker MS AAPL
field price volume price volume
0 -0.861210 -0.319607 -0.855145 0.635594
1 -1.986693 -0.526885 -1.765813 1.696533
2 -0.154544 -1.152361 -1.391477 -2.016119
3 0.621641 -0.109499 0.143788 -0.050672
由以下代码生成,请忽略作为示例的数字
columns = pd.MultiIndex.from_tuples([('MS', 'price'), ('MS', 'volume'), ('AAPL', 'price'), ('AAPL', 'volume')], names=['ticker', 'field'])
data = np.random.randn(4, 4)
df = pd.DataFrame(data, columns=columns)
现在,我想计算pct_change()或用户在每个价格列上定义的任何函数,并在“field”级别添加一个新列来存储结果
如果数据是一个面板,我知道如何优雅地完成它,因为0.20版就不推荐使用这个面板。假设面板的3个轴是日期、标记器和字段:
p[:,:, 'ret'] = p[:,:,'price'].pct_change()
就这些。但我还没有找到类似的优雅方法来处理多索引数据帧。您可以使用
IndexSlice
df.loc[:,pd.IndexSlice[:,'price']].apply(pd.Series.pct_change).rename(columns={'price':'ret'})
Out[1181]:
ticker MS AAPL
field ret ret
0 NaN NaN
1 -1.420166 -0.279805
2 3.011155 0.062529
3 -1.609004 0.759954
或
我得到了
keyrerror:“多索引切片要求索引是完全lexsorted元组len(2),lexsorted depth(0)”
def cstm(s):
return s.pct_change()
new = pd.concat(
[df.xs('price', 1, 1).apply(cstm)],
axis=1, keys=['new']
).swaplevel(0, 1, 1)
df.join(new).sort_index(1)
ticker AAPL MS
field new price volume new price volume
0 NaN -0.855145 0.635594 NaN -0.861210 -0.319607
1 1.064928 -1.765813 1.696533 1.306863 -1.986693 -0.526885
2 -0.211991 -1.391477 -2.016119 -0.922211 -0.154544 -1.152361
3 -1.103335 0.143788 -0.050672 -5.022430 0.621641 -0.109499
def cstm(s):
return s.pct_change()
df.stack(0).assign(
new=lambda d: d.groupby('ticker').price.apply(cstm)
).unstack().swaplevel(0, 1, 1).sort_index(1)