У меня есть категориальный столбец в Polars с тремя категориями 'A'
, 'B'
и 'C'
, полученными из набора обучающих данных. Столбец также содержит несколько нулей.
Теперь предположим, что в моем тестовом наборе существует ранее невиданная категория 'X'
. Я хочу справиться с этим следующим образом:
'Unknown'
в столбец обучения.'X'
) установите для них значение 'Unknown'
.Как это сделать?
Похоже, категории, которые вы хотите использовать ("A"
, "B"
, "C"
и "Unknown"
), известны заранее. В этом случае следует использовать pl.Enum.
Рассмотрим следующий пример данных.
import polars as pl
df_train = pl.DataFrame({
"cat": ["A", "B", "C"],
})
df_test = pl.DataFrame({
"cat": ["A", "X", "C"],
})
На основе данных обучения можно создать тип данных pl.Enum
, включающий дополнительную категорию "Unknown"
, следующим образом.
enum_dtype = pl.Enum(
df_train.get_column("cat").unique().drop_nulls().append(pl.Series(["Unknown"]))
)
Примечание. .drop_nulls()
используется (хотя данные в этом примере не содержат значений NULL) в качестве меры предосторожности, поскольку категории Enum не могут содержать значения NULL.
Теперь категориальный столбец в обучающем фрейме данных можно привести непосредственно к типу данных pl.Enum
.
df_train.with_columns(pl.col("cat").cast(enum_dtype))
shape: (3, 1)
┌──────┐
│ cat │
│ --- │
│ enum │
╞══════╡
│ A │
│ B │
│ C │
└──────┘
Для тестового фрейма данных это не удастся, поскольку "D"
не является известной категорией в типе данных pl.Enum
. Здесь использование strict=False
можно использовать для приведения неизвестных категорий к None
. Впоследствии пропущенные значения можно заменить категорией "Unknown"
.
df_test.with_columns(
pl.col("cat").cast(enum_dtype, strict=False).fill_null("Unknown")
)
shape: (3, 1)
┌─────────┐
│ cat │
│ --- │
│ enum │
╞═════════╡
│ A │
│ Unknown │
│ C │
└─────────┘
Редактировать. Если тестовые данные уже содержат пропущенные значения, которые следует сохранить как таковые, неизвестные значения можно явно заменить на "Unknown"
перед (строгим) приведением.
df_test.with_columns(
pl.when(
pl.col("cat").is_not_null() & ~pl.col("cat").is_in(enum_dtype.categories)
).then(
pl.lit("Unknown")
).otherwise(
pl.col("cat")
).cast(enum_dtype)
)
Спасибо! В некоторой степени это работает, пока меня не ударил TypeError: Enum categories must not contain null values
(во время работы enum_dtype = pl.Enum(df_train.get_column("cat").unique().append(pl.Series(["Unknown"])))
), что связано с наличием нулевых значений в моих тренировочных данных. Я хочу сохранить эти нули как есть (поскольку я подозреваю, что они имеют особое значение) и назначить только невидимым категориям («X») в тестовом наборе значение «Неизвестно». Как это сделать? Отредактировал вопрос.
@lpounng Рад, что это помогло. Я отредактировал свой ответ, чтобы решить проблему пропущенных значений.
Еще раз спасибо, но, похоже, возникло некоторое недопонимание - моя проблема в том, что данные обучения содержат нули, и Enum это не нравится.
@lpounng Понятно. В этом случае вы можете определить enum_dtype
, используя все категории, кроме None
: enum_dtype = pl.Enum(df_train.get_column("cat").drop_nulls().unique().append(pl.Series(["Unknown"])))
Для пояснения: столбец значений типа Enum
может содержать нули, но только категории самого типа Enum
не могут.
спасибо @orlp за разъяснения, это завершило ответ Херикса.
Вы работаете с
pl.Categorical
,pl.Enum
илиpl.String
?