Сумма значений столбцов на основе условия в pandas

#python #pandas #dataframe

#python #pandas #фрейм данных

Вопрос:

 daychange   SS
0.017065    0
-0.009259   100
0.031542    0
-0.004530   0
0.000709    0
0.004970    100
-0.021900   0
0.003611    0
  

У меня есть два столбца, и я хочу вычислить сумму следующих 5 ‘daychange’, если SS = 100.

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

 df['total'] = df.loc[df['SS'] == 100,['daychange']].sum(axis=1) 
  

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

1. Каков ваш ожидаемый результат для ваших данных примера?

2. Это должно быть около 0,0236

3. Вы не хотите sum , чтобы для второго 100 в SS ?

4. Я делаю. Для второго ‘SS = 100’ мне нужна сумма следующих 5 ‘daychange’. Например (0.0049 — 0.0219 0.0036 …). Я надеюсь, что в моих словах есть смысл

Ответ №1:

Поскольку pandas 1.1 вы можете создать окно прокрутки вперед и выбрать строки, которые вы хотите включить в свой фрейм данных. С разными аргументами ядро моего ноутбука было прекращено: используйте с осторожностью.

 indexer = pd.api.indexers.FixedForwardWindowIndexer(window_size=5)
df['total'] = df.daychange.rolling(indexer, min_periods=1).sum()[df.SS == 100]
df
  

Out:

    daychange   SS     total
0   0.017065    0       NaN
1  -0.009259  100  0.023432
2   0.031542    0       NaN
3  -0.004530    0       NaN
4   0.000709    0       NaN
5   0.004970  100 -0.013319
6  -0.021900    0       NaN
7   0.003611    0       NaN
  

Исключить начальную строку с SS == 100 из суммы

Это будет следующая строка после строк с SS == 100 . Поскольку все строки вычисляются, вы можете использовать

 df['total'] = df.daychange.rolling(indexer, min_periods=1).sum().shift(-1)[df.SS == 100]
df
  

Out:

    daychange   SS     total
0   0.017065    0       NaN
1  -0.009259  100  0.010791
2   0.031542    0       NaN
3  -0.004530    0       NaN
4   0.000709    0       NaN
5   0.004970  100 -0.018289
6  -0.021900    0       NaN
7   0.003611    0       NaN
  

Медленное хакерское решение с использованием индексов выбранных строк

Это похоже на взлом, но работает и позволяет избежать вычисления ненужных скользящих значений

 df['next5sum'] = df[df.SS == 100].index.to_series().apply(lambda x: df.daychange.iloc[x: x   5].sum())
df
  

Out:

    daychange   SS  next5sum
0   0.017065    0       NaN
1  -0.009259  100  0.023432
2   0.031542    0       NaN
3  -0.004530    0       NaN
4   0.000709    0       NaN
5   0.004970  100 -0.013319
6  -0.021900    0       NaN
7   0.003611    0       NaN
  

Для суммы следующих пяти строк, исключая строки с SS == 100 , вы можете настроить срезы или сдвинуть ряд

 df['next5sum'] = df[df.SS == 100].index.to_series().apply(lambda x: df.daychange.iloc[x   1: x   6].sum())
# df['next5sum'] = df[df.SS == 100].index.to_series().apply(lambda x: df.daychange.shift(-1).iloc[x: x   5].sum())

df
  

Out:

    daychange   SS  next5sum
0   0.017065    0       NaN
1  -0.009259  100  0.010791
2   0.031542    0       NaN
3  -0.004530    0       NaN
4   0.000709    0       NaN
5   0.004970  100 -0.018289
6  -0.021900    0       NaN
7   0.003611    0       NaN
7   0.003611    0       NaN
  

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

1. Интересный подход! Хотя кажется .rolling() , что работает намного быстрее. Например, когда я реплицирую и объединяю данные примера df = pd.concat([df for i in range(1000)]).reset_index(drop=True) , этот подход потребовал почти в 100 раз больше по сравнению с rolling предыдущим. Эта разница еще больше с большим количеством строк в данных.

2. Большое спасибо за ответ. Можете ли вы помочь с немного другой проблемой: как я могу взять сумму следующих 5 чисел на этот раз, не включая строку, где SS = 100. Например, вместо суммы строк 1-5 я беру сумму строк 2-6

3. @Ramsey — добавил это требование к моему ответу.

4. Большое спасибо. Однако, если я хочу использовать «хакерское» решение, я полагаю, мне нужно добавить .shift(-1), но в каком месте?

5. Но для более быстрого метода он выдает ошибку abt «api.indexer», что он не найден.