Средневзвешенное по группам время панды в данных панели - PullRequest
0 голосов
/ 11 марта 2019

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

stock    date     time   spread1  weight  spread2 
VOD      01-01    9:05    0.01    0.03     ...
VOD      01-01    9.12    0.03    0.05     ...
VOD      01-01   10.04    0.02    0.30     ...
VOD      01-02   11.04    0.02    0.05
...       ...     ...     ....     ...
BAT      01-01   0.05     0.04    0.03
BAT      01-01   0.07     0.05    0.03
BAT      01-01   0.10     0.06    0.04

Я хочу рассчитать средневзвешенное значение spread1 для каждой акции в каждый день. Я могу разбить решение на несколько шагов. то есть я могу применить функции groupby и agg, чтобы получить сумму веса спреда 1 * для каждой акции в каждый день в dataframe1, а затем вычислить сумму веса для каждой акции в каждый день в dataframe2. После этого merge два набора данных и получим средневзвешенное значение для спреда1.

Мой вопрос: есть ли здесь простой способ расчета средневзвешенного спреда1? У меня также есть распространение2, распространение3 и распространение4. Поэтому я хочу написать как можно меньше кода. Спасибо

1 Ответ

1 голос
/ 11 марта 2019

IIUC, вам нужно transform вернуть результат к оригиналу, но использовать .transform с выводом, который зависит от двух столбцов, довольно сложно.Мы пишем нашу собственную функцию, в которой мы передаем серию спредов s и исходный DataFrame df, поэтому мы также можем использовать весовые коэффициенты:

import numpy as np

def weighted_avg(s, df):
    return np.average(s, weights=df.loc[df.index.isin(s.index), 'weight'])

df['spread1_avg'] = df.groupby(['stock', 'date']).spread1.transform(weighted_avg, df)

Выходные данные:

  stock   date   time  spread1  weight  spread1_avg
0   VOD  01-01   9:05     0.01    0.03     0.020526
1   VOD  01-01   9.12     0.03    0.05     0.020526
2   VOD  01-01  10.04     0.02    0.30     0.020526
3   VOD  01-02  11.04     0.02    0.05     0.020000
4   BAT  01-01   0.05     0.04    0.03     0.051000
5   BAT  01-01   0.07     0.05    0.03     0.051000
6   BAT  01-01   0.10     0.06    0.04     0.051000

При необходимости для нескольких столбцов:

gp = df.groupby(['stock', 'date'])
for col in [f'spread{i}' for i in range(1,5)]:
    df[f'{col}_avg'] = gp[col].transform(weighted_avg, df)

В качестве альтернативы, если вам не нужно преобразовывать обратно и получить одно значение на дату акции:

def my_avg2(gp):
    avg = np.average(gp.filter(like='spread'), weights=gp.weight, axis=0)
    return pd.Series(avg, index=[col for col in gp.columns if col.startswith('spread')])    

### Create some dummy data
df['spread2'] = df.spread1+1
df['spread3'] = df.spread1+12.1
df['spread4'] = df.spread1+1.13

df.groupby(['stock', 'date'])[['weight'] + [f'spread{i}' for i in range(1,5)]].apply(my_avg2)

#              spread1   spread2    spread3   spread4
#stock date                                          
#BAT   01-01  0.051000  1.051000  12.151000  1.181000
#VOD   01-01  0.020526  1.020526  12.120526  1.150526
#      01-02  0.020000  1.020000  12.120000  1.150000
...