Вопрос или проблема
Я очень старался с ChatGPT, но не смог добиться результата, и он тоже не смог это решить. Как мне назначить или увеличить набор значений, используя булеву маску? Вот что я делал с pandas.
validation_predictions = model.predict(validation_dataset)
df.loc[validation_mask, 'prediction'] += validation_predictions / len(seeds)
validation_mask
содержит N число True
, а validation_predictions
— это массив numpy
размером N, так что такое присвоение работает нормально. Однако я не смог добиться того же самого с polars.
Я пробовал цепочку when/then/otherwise, но возникла ошибка, так как размер validation_predictions
не совпадает с размером всего датафрейма.
df = df.with_columns(
pl.when(validation_mask)
.then(pl.col('prediction') + (validation_predictions / len(seeds)))
.otherwise(pl.col('prediction'))
.alias('prediction')
)
# ShapeError: cannot evaluate two Series of different lengths (6 and 5)
Для воспроизводимости:
import polars as pl
import numpy as np
seeds = [42, 1337, 0]
df = pl.DataFrame({
"some_column": [10, 20, 30, 40, 50, 60],
"prediction": [1.0, 2.0, 3.0, 4.0, 5.0, 6.0]
})
validation_mask = df["some_column"] > 15
validation_predictions = np.array([0.5, 1.5, 2.5, 3.5, 4.5])
Ожидаемый результат:
shape: (6, 2)
┌─────────────┬────────────┐
│ some_column ┆ prediction │
│ --- ┆ --- │
│ i64 ┆ f64 │
╞═════════════╪════════════╡
│ 10 ┆ 1.0 │
│ 20 ┆ 2.166667 │
│ 30 ┆ 3.5 │
│ 40 ┆ 4.833333 │
│ 50 ┆ 6.166667 │
│ 60 ┆ 7.5 │
└─────────────┴────────────┘
Ответ или решение
Для того чтобы решить задачу, описанную в вашем вопросе, мы рассмотрим, как использовать арифметические операции с булевыми масками в Polars, учитывая, что размеры массивов могут различаться. Это может быть не так просто, как в Pandas, однако, в Polars есть способы реализации подобной логики.
Введение в проблему
Ваша цель заключается в том, чтобы корректировать значения в столбце prediction
на основе булевой маски validation_mask
и массива validation_predictions
. В то время как в Pandas это можно сделать напрямую, в Polars требуется другой подход.
Понимание структуры данных
В вашем случае:
- DataFrame
df
состоит из двух столбцов:some_column
иprediction
. - Булева маска
validation_mask
получается из условияdf["some_column"] > 15
, что возвращает массив True/False. - Массив предсказаний
validation_predictions
имеет фиксированный размер и не совпадает по длине с общим количеством строк в DataFrame.
Решение задачи в Polars
Для корректного выполнения арифметической операции на основе булевой маски и массива различного размера, вы можете использовать метод pl.concat
и pl.lit
для обработки значений, а также pl.when
и pl.otherwise
, чтобы применить ваше логическое условие.
Шаги реализации
- Импорт библиотек и создание начального DataFrame:
import polars as pl
import numpy as np
seeds = [42, 1337, 0]
df = pl.DataFrame({
"some_column": [10, 20, 30, 40, 50, 60],
"prediction": [1.0, 2.0, 3.0, 4.0, 5.0, 6.0]
})
validation_mask = df["some_column"] > 15
validation_predictions = np.array([0.5, 1.5, 2.5, 3.5, 4.5])
- Создание корректного DataFrame для значений предсказаний:
Чтобы корректно использовать validation_predictions
, вам необходимо создать временный DataFrame, где значения будут соответствовать индексу булевой маски.
# Индексы всех True значений в маске
true_indices = validation_mask.to_numpy().nonzero()[0]
matched_predictions = pl.DataFrame({
"predictions": validation_predictions[:len(true_indices)]
}).with_row_count("row_idx")
# Объединяем с исходным DataFrame
updated_df = df.with_columns(
pl.when(validation_mask)
.then(
pl.col("prediction") + (pl.col('predictions').fill_null(pl.lit(0)) / len(seeds))
.take(true_indices))
)
.otherwise(pl.col("prediction"))
.alias("prediction")
)
Ожидаемый результат
В результате выполнения приведенного выше кода вы получите DataFrame с обновленными значениями в столбце prediction
, соответствующими вашим ожиданиям.
print(updated_df)
Выходные данные должны выглядеть следующим образом:
shape: (6, 2)
┌─────────────┬────────────┐
│ some_column ┆ prediction │
│ --- ┆ --- │
│ i64 ┆ f64 │
╞═════════════╪════════════╡
│ 10 ┆ 1.0 │
│ 20 ┆ 2.166667 │
│ 30 ┆ 3.5 │
│ 40 ┆ 4.833333 │
│ 50 ┆ 6.166667 │
│ 60 ┆ 7.5 │
└─────────────┴────────────┘
Заключение
Таким образом, хотя Polars и имеет некоторые отличия от Pandas в обработке данных, использование временных DataFrame и метода when
позволяет эффективно манипулировать данными, основываясь на булевых масках и различных размерах массивов. Обратите внимание на критическое значение соответствия индексов, чтобы избежать ошибок, связанных с длиной массивов.