Оптимизация группы данных - переходящий - примените и добавьте столбец обратно исходный кадр данных - PullRequest
0 голосов
/ 07 февраля 2019

У меня есть DataFrame с данными нескольких временных рядов.Фиктивный пример:

df = pd.DataFrame({
    'node': [1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2],
    'seq': [0,1,2,3,4,5,6,7,8,9] * 2,
    'values': [1,2,4,8,16,32,64,128,256,512] * 2,
}).sample(frac=1).reset_index(drop=True) 

Данные неупорядоченные .Вот почему я добавил .sample(...) и .reset_index(...), чтобы перемешать.Пример DataFrame будет выглядеть примерно так:

    node  seq  values
0      2    0       1
1      1    5      32
2      2    3       8
3      1    9     512
4      1    4      16
5      2    2       4
6      1    2       4
7      1    7     128
8      1    6      64
9      1    0       1
10     2    9     512
11     2    1       2
12     1    8     256
13     1    1       2
14     2    5      32
15     2    7     128
16     1    3       8
17     2    6      64
18     2    8     256
19     2    4      16

На этапе предварительной обработки эти две серии в примере не связаны между собой.Теперь я хотел бы добавить столбец со скользящими средними значениями, например.Как я это делаю сейчас:

roll_mean = df.groupby('node', as_index=False) \
    .apply(lambda g: g.sort_values('seq')['values'].rolling(4).mean()) \
    .reset_index(level=0)['values']

# add column
df['rollMean4'] = roll_mean

Есть ли лучший способ сделать это?

1 Ответ

0 голосов
/ 07 февраля 2019

Вы можете sort_values до groupby, поэтому применять следует опустить:

np.random.seed(2019)

df = pd.DataFrame({
    'node': [1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2],
    'seq': [0,1,2,3,4,5,6,7,8,9] * 2,
    'values': [1,2,4,8,16,32,64,128,256,512] * 2,
}).sample(frac=1).reset_index(drop=True) 
#print (df)

Если используется сортировка по одному столбцу (Series), используется по умолчанию quicksort:

roll_mean = (df.groupby('node', as_index=False) 
               .apply(lambda g: g.sort_values('seq')['values'].rolling(4).mean()) 
               .reset_index(level=0)['values'])

Для одинаковых значений в реальных данных необходимо установить kind='mergesort':

roll_mean = (df.groupby('node', as_index=False) 
               .apply(lambda g: g.sort_values('seq', kind='mergesort')['values']
                                  .rolling(4).mean()) 
               .reset_index(level=0)['values'])

Если используется сортировка по нескольким столбцам по умолчанию mergesort:

roll_mean1 = (df.sort_values(['seq','node'])
               .groupby('node', as_index=False)['values']
               .rolling(4)
               .mean() 
               .reset_index(level=0, drop=True))


# add column
df['rollMean4'] = roll_mean
df['rollMean41'] = roll_mean1

print (df)
    node  seq  values  rollMean4  rollMean41
0      1    9     512     240.00      240.00
1      2    4      16       7.50        7.50
2      1    1       2        NaN         NaN
3      2    1       2        NaN         NaN
4      1    6      64      30.00       30.00
5      1    2       4        NaN         NaN
6      2    6      64      30.00       30.00
7      1    4      16       7.50        7.50
8      1    3       8       3.75        3.75
9      2    7     128      60.00       60.00
10     2    9     512     240.00      240.00
11     1    7     128      60.00       60.00
12     2    3       8       3.75        3.75
13     1    0       1        NaN         NaN
14     2    0       1        NaN         NaN
15     2    2       4        NaN         NaN
16     2    5      32      15.00       15.00
17     1    5      32      15.00       15.00
18     2    8     256     120.00      120.00
19     1    8     256     120.00      120.00

Новый образец:

np.random.seed(2019)

df = pd.DataFrame({
    'node': [1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2] * 10,
    'seq': [0,1,2,3,4,5,6,7,8,9] * 20,
    'values': [1,2,4,8,16,32,64,128,256,512] * 20,
}).sample(frac=1).reset_index(drop=True) 
print (df)

roll_mean1 = (df.groupby('node', as_index=False) 
               .apply(lambda g: g.sort_values('seq')['values'].rolling(4).mean()) 
               .reset_index(level=0)['values'])

roll_mean2 = (df.groupby('node', as_index=False) 
               .apply(lambda g: g.sort_values('seq', kind='mergesort')['values'].rolling(4).mean()) 
               .reset_index(level=0)['values'])

roll_mean3 = (df.sort_values(['seq','node'])
               .groupby('node', as_index=False)['values']
               .rolling(4)
               .mean() 
               .reset_index(level=0, drop=True))

# add column
df['rollMean41'] = roll_mean1
df['rollMean42'] = roll_mean2
df['rollMean43'] = roll_mean3
print (df.head())
   node  seq  values  rollMean41  rollMean42  rollMean43
0     2    3       8         5.0         5.0         5.0
1     2    7     128       128.0        80.0        80.0
2     2    0       1         1.0         NaN         NaN
3     2    8     256       160.0       160.0       160.0
4     1    5      32        20.0        20.0        20.0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...