Pandas Cumsum условный сброс - PullRequest
0 голосов
/ 04 мая 2020

Я использую существующее решение, чтобы попытаться получить кумулятивную сумму, которая сбрасывается после определенного значения (в данном случае> = 16). В настоящее время я получаю следующий вывод, но есть случаи, когда сумма все еще больше 16.

Size    cumsum
8       8
8       16     ---correct
8       8
8       16     ---correct
7       7
6       13     (should be reset here since next value causes cumsum >16)
7       20     ---incorrect
6       6
5       11
2       13

Код, который я использую:

df = pd.DataFrame({'Size':[8,8,8,8,7,6,7,6,5,2]})

ls = []  
cumsum = 0
last_reset = 0
for _, row in df.iterrows():
    cumsum = cumsum + row.Size
    ls.append(cumsum)
    if cumsum >= 16:
        last_reset = cumsum
        cumsum = 0 
df['cumsum'] = ls

Любые идеи, как исправить это?

Ответы [ 3 ]

1 голос
/ 04 мая 2020

Небольшое отклонение принятого ответа здесь: Выполните кумулятивную сумму по столбцу, но сбросьте до 0, если сумма станет отрицательной в Pandas, может помочь вам решить эту проблему.

Поскольку это решение использует Numba, это будет намного быстрее, чем обычно iterrows решение

@njit
def cumli(x, lim):
    total = 0
    result = []
    for i, y in enumerate(x):
        total += y
        if (total) > lim:
            total = y
        result.append(total)
    return result

cumli(df.Size.values, 16)

# [8, 16, 8, 16, 7, 13, 7, 13, 5, 7]
1 голос
/ 04 мая 2020
df = pd.DataFrame({'Size':[8,8,8,8,7,6,7,6,5,2]})

ls = []  
cumsum = 0
last_reset = 0
for _, row in df.iterrows():
    if cumsum + row.Size <= 16:
        cumsum += row.Size
    else:
        last_reset = cumsum
        cumsum = row.Size
    ls.append(cumsum)

df['cumsum'] = ls

Результат:

    Size    cumsum
0   8       8
1   8       16
2   8       8
3   8       16
4   7       7
5   6       13
6   7       7
7   6       13
8   5       5
9   2       7
0 голосов
/ 04 мая 2020

Я думаю, хорошее решение - это «функция с памятью», которая будет применяться к каждому значению из интересующего вас столбца.

Определите следующую функцию для расчета вашей суммы:

def myCumSum(val):
    myCumSum.sum += val
    if myCumSum.sum > 16:
        myCumSum.sum = val
    return myCumSum.sum

Обратите внимание, что эта функция имеет атрибут ( sum ), который должен быть установлен перед первым вызовом этой функции.

myCumSum.sum = 0

Затем примените его к Размер столбец и сохраните результат как cumsum столбец:

df['cumsum'] = df.Size.apply(myCumSum)
...