Мне нужно просмотреть фрейм данных и обновить оценку в столбце 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
Вы можете использовать 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, как в вашем примере.
Я прочитал ответ @e-motta несколько раз, прежде чем получил его. Согласно вашему примеру, первая запись в столбце 2 равна нулю. Вторая — это первая запись в столбце 1 (плюс ноль). Третья — это вторая запись в столбце 2 (= первая запись в столбце 1) плюс вторая запись в столбце 1, т. е. сумма первых двух записей в столбце 1. Если мы продолжим, n-я запись в столбце 2 будет (n-1)-я запись в столбце 1 плюс (n-1)-я запись в столбце 2, которая, в свою очередь, представляет собой совокупную сумму первых (n-2) членов в столбце 1.
@ Тим, я понимаю, но обратите внимание, что если вы примените свою логику, значение из столбца 2 будет суммой всех предыдущих значений из столбца 1, и это обобщается до кумулятивной суммы. Вы можете убедиться в этом, используя свой код в том же наборе данных. Конечно, это работает, только если вы хотите суммировать значения; если вам нужно выполнить другие операции, вам нужно будет адаптировать это или даже использовать другой подход, но это не указано в вашем вопросе (вы можете отредактировать и уточнить его, если это так).
@e-motta ты прав. Я пытался упростить проблему, чтобы поделиться ею с SO, но на самом деле упустил важную часть. Я хочу изменить каждую строку с помощью DECAY, прежде чем будет рассчитана следующая строка - см. редактирование. Пол Уилсон, спасибо за объяснение.
@Tim Это немного сложнее, но вы можете сделать это, используя numpy
. Смотрите мой обновленный ответ.
@e-motta работает правильно, и я отметил правильно. Однако размер кадра данных составляет 66 КБ, поэтому память, необходимая для создания массива 66 х 66 КБ, ограничивает его эффективность меньшими размерами df. Я понимаю, что это не входило в первоначальный объем вопроса, но если у вас есть какие-либо способы обойти это, я буду признателен.
Я добавил это @ScottBoston. Не дополнительные правки, касающиеся DECAY.