У меня есть пандас dataframe с двумя столбцами, как это,
Item Value
0 A 7
1 A 2
2 A -6
3 A -70
4 A 8
5 A 0
Я хочу накапливать сумму по столбцу, Value
. Но при создании кумулятивной суммы, если значение становится отрицательным, я хочу сбросить его обратно на 0.
В настоящее время я использую цикл, показанный ниже, чтобы выполнить это,
sum_ = 0
cumsum = []
for val in sample['Value'].values:
sum_ += val
if sum_ < 0:
sum_ = 0
cumsum.append(sum_)
print(cumsum) # [7, 9, 3, 0, 8, 8]
Я ищу более эффективный способ сделать это в чистых пандах.
2 ответа
Немного измените также этот метод медленно, что numba
sumlm = np.frompyfunc(lambda a,b: 0 if a+b < 0 else a+b,2,1)
newx=sumlm.accumulate(df.Value.values, dtype=np.object)
newx
Out[147]: array([7, 9, 3, 0, 8, 8], dtype=object)
numba
решение
from numba import njit
@njit
def cumli(x, lim):
total = 0
result = []
for i, y in enumerate(x):
total += y
if total < lim:
total = 0
result.append(total)
return result
cumli(df.Value.values,0)
Out[166]: [7, 9, 3, 0, 8, 8]
Это всего лишь комментарий WeNYoBen.
Если вы можете избежать списков, обычно рекомендуется избегать этого.
Пример
from numba import njit
import numpy as np
#with lists
@njit()
def cumli(x, lim):
total = 0
result = []
for i, y in enumerate(x):
total += y
if total < lim:
total = 0
result.append(total)
return result
#without lists
@njit()
def cumli_2(x, lim):
total = 0.
result = np.empty_like(x)
for i, y in enumerate(x):
total += y
if total < lim:
total = 0.
result[i]=total
return result
Время
Без Numba (комментарий @ njit ()):
x=(np.random.rand(1_000)-0.5)*5
%timeit a=cumli(x, 0.)
220 µs ± 2.25 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit a=cumli_2(x, 0.)
227 µs ± 1.95 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
Нет разницы между использованием списков или массивов. Но это не тот случай, если вы Jit-компилируете эту функцию.
С Numba:
%timeit a=cumli(x, 0.)
27.4 µs ± 210 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%timeit a=cumli_2(x, 0.)
2.96 µs ± 32.5 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
Даже в немного более сложных случаях (конечный размер массива неизвестен или известен только максимальный размер массива) часто имеет смысл выделить массив и сжать его в конце, или в простых случаях даже запустить алгоритм один раз, чтобы узнать конечный массив Размер и чем сделать реальный расчет.
Похожие вопросы
Связанные вопросы
Новые вопросы
python
Python — это мультипарадигмальный многоцелевой язык программирования с динамической типизацией. Он предназначен для быстрого изучения, понимания и использования, а также обеспечивает чистый и унифицированный синтаксис. Обратите внимание, что Python 2 официально не поддерживается с 01.01.2020. Если у вас есть вопросы о версии Python, добавьте тег [python-2.7] или [python-3.x]. При использовании варианта Python (например, Jython, PyPy) или библиотеки (например, Pandas, NumPy) укажите это в тегах.