Смещение скользящего среднего в groupby без преобразования?

#python #pandas #pandas-groupby #rolling-computation

Вопрос:

 a = df.groupby("RaceID")["wS"].transform(lambda x: x.expanding().mean().shift())
b = df.groupby("RaceID")["wS"].expanding().mean().shift().sort_index(level=1).droplevel(0)
 

Я получаю правильный результат, если запускаю первую строку. С другой стороны, второй подход быстрее. Это также отлично работает, если я не использую shift, это перемещает все значения скользящего среднего для каждой группы на один шаг вперед.

         RaceID  transform   notransform noshift
7140    1021458 0.215909    0.215909    0.191919
7141    1021459 NaN         0.191919    2.375000
7142    1021459 2.375000    2.375000    1.187500
7143    1021459 1.187500    1.187500    0.791667
7144    1021459 0.791667    0.791667    0.593750
7145    1021459 0.593750    0.593750    0.475000
7146    1021459 0.475000    0.475000    0.395833
7147    1021459 0.395833    0.395833    0.339286
7148    1021459 0.339286    0.339286    0.296875
7149    1021460 NaN         0.296875    10.000000
 

Преобразование столбца является результатом первой строки, и никакое преобразование не является результатом второй строки.

Как вы можете видеть в соответствии с индексом 7141, преобразование правильно устанавливает первое значение NaN при перемещении группы. Операция без преобразования фактически правильно перемещает элементы, однако она устанавливает первое значение на последнее значение предыдущей группы. Это поведение видно в соответствии с индексом 1021460.

Данные-пример:

         RaceID  wS
7130    1017734 0.000000
7131    1017734 0.000000
7132    1021458 1.727273
7133    1021458 0.000000
7134    1021458 0.000000
7135    1021458 0.000000
7136    1021458 0.000000
7137    1021458 0.000000
7138    1021458 0.000000
7139    1021458 0.000000
7140    1021458 0.000000
7141    1021459 2.375000
7142    1021459 0.000000
7143    1021459 0.000000
7144    1021459 0.000000
7145    1021459 0.000000
7146    1021459 0.000000
7147    1021459 0.000000
7148    1021459 0.000000
7149    1021460 10.000000
7150    1021460 0.000000
7151    1021460 0.000000
7152    1021460 0.000000
7153    1021460 0.000000
7154    1021460 0.000000
7155    1021460 0.000000
7156    1021460 0.000000
7157    1021460 0.000000
7158    1021460 0.000000
7159    1021460 0.000000
7160    1021460 0.000000
7161    1021460 0.000000
7162    1021460 0.000000
7163    1021460 0.000000
7164    1021460 0.000000
7165    1021460 0.000000
7166    1021460 0.000000
7167    1021461 201.000000
 

Комментарии:

1. образец ваших входных данных был бы полезен здесь

2. Ваши данные отсортированы по расеидам, как в вашем примере?

3. @Ben. — Я в этом не разбирался. Я не уверен, насколько это здесь уместно.

4. вы могли mask бы использовать первый элемент каждого RaceID, если они упорядочены, потому что ваша проблема заключается только в том, что во второй строке shift не выполняется для каждой группы, а с упорядоченными данными можно замаскировать первый элемент каждой группы

5. @Ben. Т спасибо, это одно из решений.

Ответ №1:

В первом примере сдвиг происходит до возвращения. Во втором это происходит позже, поэтому данные больше не группируются, когда происходит сдвиг.

Вероятно, вы захотите снова сгруппироваться после среднего значения, чтобы сдвиг выполнялся по группам.

 import pandas as pd
df = pd.DataFrame({'group':[1,1,1,2,2,2], 'values':[1,2,3,10,20,30]})

df.groupby("group", as_index=False)["values"].expanding().mean().groupby(level=0).shift().sort_index(level=1).droplevel(0)
 

Выход

 0     NaN
1     1.0
2     1.5
3     NaN
4    10.0
5    15.0
 

Комментарии:

1. Спасибо, хорошее решение. Скорость тоже не сильно страдает, все равно намного быстрее, чем трансформация.