Присвоение значения первой строке мультииндекса данных

64
6

У меня есть кадр данных с многоуровневыми индексами, который выглядит примерно так:

                 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

спросил(а) 2021-01-19T17:02:51+03:00 6 месяцев, 1 неделя назад
1
Решение
64

Вы можете использовать groupby, например

df['diffs'] = df.values.groupby(level=0).apply(lambda x: (xx.shift(1)).fillna(0))

ответил(а) 2021-01-19T17:02:51+03:00 6 месяцев, 1 неделя назад
45

вероятно, лучший способ, но это работает, сначала мы видим, что мультииндекс состоит из разных уровней и меток, эти ярлыки показывают нам, когда уровень изменяется:

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

ответил(а) 2021-01-19T17:02:51+03:00 6 месяцев, 1 неделя назад
45

Один простой подход к решению проблемы заключается в транспонировании кадра данных и применении цикла.

T = df.T
for name in T.columns.levels[0]:
T.loc[T.index[-1], name][0]=0

Например, с вашими данными вы получите следующее: (Я не добавлял имена, и я просто отвечаю NaN на -1)

data=np.array([[ 0.55, -1], [-2.50,  -3.05], [-0.79,  -0.56],
[-1.01, -0.22], [-1.24, -0.23], [-1.29, -0.05], [ 1.65, 2.94]])

index=[np.array(['A', 'A', 'A', 'B', 'B', 'C', 'C']),
np.array(['22', '32', '76', '59', '72', '22', '63'])]

df=pd.DataFrame(data,index=index)
df
0 1
A 22 0.55 -1.00
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

T = df.T
for name in T.columns.levels[0]:
T.loc[T.index[-1], name][0]=0

df
0 1
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

ответил(а) 2021-01-19T17:02:51+03:00 6 месяцев, 1 неделя назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема