Векторизация цикла доступа к предыдущим значениям построчно

Мне нужно просмотреть фрейм данных и обновить оценку в столбце 2 на основе предыдущего значения в столбце 1 и столбце 2. Я ищу идеи о том, как векторизовать этот подход/ускорить его, поскольку в настоящее время это довольно затратно в цикле. формат ниже. Первая строка имеет значение 0, поскольку предшествующего значения нет.

df = pd.DataFrame({'column1': [1, 2, 3, 4, 5]})

for idx, row in df.iterrows():
    if idx == 0:
        df.loc[idx, 'column2'] = 0
    else:
        df.loc[idx, 'column2'] = (df.loc[idx - 1, 'column1'] + df.loc[idx - 1, 'column2']) * DECAY

# Expected output -

   column1  column2
0        1      0.0
1        2      0.9
2        3      2.61
3        4      5.049
4        5     8.1441

Я добавил это @ScottBoston. Не дополнительные правки, касающиеся DECAY.

Tim 08.08.2024 09:46
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
1
67
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете использовать numpy, чтобы получить скалярное произведение матрицы, которая учитывает DECAY:

df = pd.DataFrame({"column1": [1, 2, 3, 4, 5]})

DECAY = 0.9

n = len(df)
dm = np.tril(np.power(DECAY, np.subtract.outer(np.arange(n), np.arange(n))), -1)
df["column2"] = dm.dot(df["column1"])
   column1  column2
0        1   0.0000
1        2   0.9000
2        3   2.6100
3        4   5.0490
4        5   8.1441

Промежуточные шаги для ясности:

Создайте матрицу m вычитанием всех пар из массива с диапазоном [0, n]:

m = np.subtract.outer(np.arange(n), np.arange(n))
[[ 0 -1 -2 -3 -4]
 [ 1  0 -1 -2 -3]
 [ 2  1  0 -1 -2]
 [ 3  2  1  0 -1]
 [ 4  3  2  1  0]]

Возвысьте DECAY до степени каждого элемента в m:

p = np.power(DECAY, m)
[[1.         1.11111111 1.2345679  1.37174211 1.5241579 ]
 [0.9        1.         1.11111111 1.2345679  1.37174211]
 [0.81       0.9        1.         1.11111111 1.2345679 ]
 [0.729      0.81       0.9        1.         1.11111111]
 [0.6561     0.729      0.81       0.9        1.        ]]

Сохраните нижний треугольник матрицы:

dm = np.tril(p, -1)
[[0.     0.     0.     0.     0.    ]
 [0.9    0.     0.     0.     0.    ]
 [0.81   0.9    0.     0.     0.    ]
 [0.729  0.81   0.9    0.     0.    ]
 [0.6561 0.729  0.81   0.9    0.    ]]

Спасибо. Если вы внимательно посмотрите, результат в столбце 2 является результатом данных как в столбце 1, так и в столбце 2, а не только в столбце 1, как в вашем примере.

Tim 07.08.2024 21:50

Я прочитал ответ @e-motta несколько раз, прежде чем получил его. Согласно вашему примеру, первая запись в столбце 2 равна нулю. Вторая — это первая запись в столбце 1 (плюс ноль). Третья — это вторая запись в столбце 2 (= первая запись в столбце 1) плюс вторая запись в столбце 1, т. е. сумма первых двух записей в столбце 1. Если мы продолжим, n-я запись в столбце 2 будет (n-1)-я запись в столбце 1 плюс (n-1)-я запись в столбце 2, которая, в свою очередь, представляет собой совокупную сумму первых (n-2) членов в столбце 1.

Paul Wilson 07.08.2024 22:24

@ Тим, я понимаю, но обратите внимание, что если вы примените свою логику, значение из столбца 2 будет суммой всех предыдущих значений из столбца 1, и это обобщается до кумулятивной суммы. Вы можете убедиться в этом, используя свой код в том же наборе данных. Конечно, это работает, только если вы хотите суммировать значения; если вам нужно выполнить другие операции, вам нужно будет адаптировать это или даже использовать другой подход, но это не указано в вашем вопросе (вы можете отредактировать и уточнить его, если это так).

e-motta 08.08.2024 00:09

@e-motta ты прав. Я пытался упростить проблему, чтобы поделиться ею с SO, но на самом деле упустил важную часть. Я хочу изменить каждую строку с помощью DECAY, прежде чем будет рассчитана следующая строка - см. редактирование. Пол Уилсон, спасибо за объяснение.

Tim 08.08.2024 09:24

@Tim Это немного сложнее, но вы можете сделать это, используя numpy. Смотрите мой обновленный ответ.

e-motta 08.08.2024 14:11

@e-motta работает правильно, и я отметил правильно. Однако размер кадра данных составляет 66 КБ, поэтому память, необходимая для создания массива 66 х 66 КБ, ограничивает его эффективность меньшими размерами df. Я понимаю, что это не входило в первоначальный объем вопроса, но если у вас есть какие-либо способы обойти это, я буду признателен.

Tim 08.08.2024 14:46

Другие вопросы по теме