我有一个带有多级索引的数据框,看起来有点像这样:
value diffs
ticker date
A 22 0.55 NaN
32 -2.50 -3.05
76 -0.79 -0.56
B 59 -1.01 -0.22
72 -1.24 -0.23
C 22 -1.29 -0.05
63 1.65 2.94
如何更改每个级别的第一行,以便我可以获得:
value diffs
ticker date
A 22 0.55 0
32 -2.50 -3.05
76 -0.79 -0.56
B 59 -1.01 0
72 -1.24 -0.23
C 22 -1.29 0
63 1.65 2.94
答案 0 :(得分:1)
您可以使用groupby
,例如
df['diffs'] = df.values.groupby(level=0).apply(lambda x: (x-x.shift(1)).fillna(0))
答案 1 :(得分:0)
可能有一种更好的方法,但这有效,首先我们可以看到多索引由不同的级别和标签组成,标签在级别更改时向我们显示:
In [77]:
df.index
Out[77]:
MultiIndex(levels=[['A', 'B', 'C'], [22, 32, 59, 63, 72, 76]],
labels=[[0, 0, 0, 1, 1, 2, 2], [0, 1, 5, 2, 4, 0, 3]],
names=['ticker', 'date'])
因此我们可以从第一个标签数组构建一个系列,并使用shift
检测关卡何时更改并使用它来索引df:
In [78]:
labels = pd.Series(df.index.labels[0])
labels[labels != labels.shift()]
Out[78]:
0 0
3 1
5 2
dtype: int8
从上面的索引我们可以传递到iloc
以选择每个顶级组的第一行:
In [82]:
df['diffs'].iloc[labels[labels != labels.shift()].index]
Out[82]:
ticker date
A 22 NaN
B 59 -0.22
C 22 -0.05
Name: diffs, dtype: float64
我们现在可以分配值:
In [83]:
df['diffs'].iloc[labels[labels != labels.shift()].index] = 0
df
Out[83]:
value diffs
ticker date
A 22 0.55 0.00
32 -2.50 -3.05
76 -0.79 -0.56
B 59 -1.01 0.00
72 -1.24 -0.23
C 22 -1.29 0.00
63 1.65 2.94
答案 2 :(得分:0)
解决问题的一种简单方法是转置数据框并应用循环。
T = df.T
for name in T.columns.levels[0]:
T.loc[T.index[-1], name][0]=0
例如,根据您的数据,您将获得以下信息:
(我没有添加姓名,我只是回复了NaN
的{{1}})
-1