В Pandas вы можете создать «упорядоченный» категориальный столбец из существующего строкового столбца следующим образом:
column_values_with_custom_order = ["B", "A", "C"] df["Column"] = pd.Categorical(df.Column, categories=column_values_with_custom_order, ordered=True)
В документации Polars я не смог найти такой способ создания упорядоченных столбцов. Однако я мог воспроизвести это с помощью pl.from_pandas(df)
, поэтому я подозреваю, что это возможно и с Polars.
Каким будет рекомендуемый способ для этого?
Я попытался создать новый столбец с помощью polars_df.with_columns(col("Column").cast(pl.categorical))
, но я не знаю, как включить в него пользовательский порядок.
Еще проверила В полярах можно ли самому создать категориальный тип с уровнями?, но я бы предпочел не добавлять еще один столбец в свой Dataframe только для упорядочения.
Теперь я замечаю, что связанный ответ фактически содержит решение моего вопроса. Спасибо, что заметили это.
Из документа: Использовать:
polars_df.with_columns(col("Column").cast(pl.categorical).cat.set_ordering("lexical"))
Смотрите документ
df = pl.DataFrame(
{"cats": ["z", "z", "k", "a", "b"], "vals": [3, 1, 2, 2, 3]}
).with_columns(
[
pl.col("cats").cast(pl.Categorical).cat.set_ordering("lexical"),
]
)
df.sort(["cats", "vals"])
Я полагаю, что это просто упорядочение по алфавиту? Что, если бы я хотел определить порядок как ["k", "z", "b", "a"]. Я не думаю, что это сработает тогда. Результат кода: форма: (5, 2) коты вальс кот i64 "а" 2 "б" 3 "к" 2 "г" 1 "г" 3
Я думаю, вы можете сделать set_ordering("physical")
, но категории должны отображаться в том порядке, в котором вы хотите, чтобы они были.
Скажи, что у тебя есть
df = pl.DataFrame(
{"cats": ["z", "z", "k", "a", "b"], "vals": [3, 1, 2, 2, 3]}
)
и вы хотите сделать кошек категориальными, но вы хотите, чтобы категориальные упорядочены как
myorder=["k", "z", "b", "a"]
Есть два способа сделать это. Один из способов — pl.StringCache()
, как в вопросе, на который вы ссылаетесь, а другой — более запутанный. Первый не требует добавления каких-либо столбцов в ваш df. На самом деле очень лаконично.
with pl.StringCache():
pl.Series(myorder).cast(pl.Categorical)
df=df.with_columns(pl.col('cats').cast(pl.Categorical))
Что происходит, так это то, что все в StringCache получает одинаковые значения ключей, поэтому при приведении списка myorder
сохраняется, какие ключи выделяются для каждого строкового значения. Когда ваш df попадает в тот же кеш, он получает те же значения ключа/строки, которые находятся в том порядке, в котором вы хотели.
Другой способ сделать это заключается в следующем:
Вы должны отсортировать свой df по порядку, тогда вы можете сделать set_ordering('physical')
. Если вы хотите сохранить свой первоначальный порядок, вам просто нужно использовать with_row_count
в начале, чтобы вы могли восстановить этот порядок.
Собрав все вместе, это выглядит так:
df=df.with_row_count('i').join(
pl.from_dicts([{'order':x, 'cats':y} for x,y in enumerate(myorder)]), on='cats') \
.sort('order').drop('order') \
.with_columns(pl.col('cats').cast(pl.Categorical).cat.set_ordering('physical')) \
.sort('i').drop('i')
Вы можете проверить, выполнив:
df.select(['cats',pl.col('cats').to_physical().alias('phys')])
shape: (5, 2)
┌──────┬──────┐
│ cats ┆ phys │
│ --- ┆ --- │
│ cat ┆ u32 │
╞══════╪══════╡
│ z ┆ 1 │
│ z ┆ 1 │
│ k ┆ 0 │
│ a ┆ 3 │
│ b ┆ 2 │
└──────┴──────┘
Спасибо за ясное объяснение! Это ответило на мой вопрос.
Обратите внимание, что в связанном ответе в DataFrame не добавляется еще один столбец… просто создается небольшая серия с желаемым порядком, пока действует StringCache. Цель этой начальной серии - установить порядок строк и ничего больше. Его можно даже отбросить и никогда не добавлять в какой-либо DataFrame. Затем, пока тот же StringCache остается в силе, любые последующие столбцы категорий в любом DatFrame будут соблюдать порядок исходной серии, даже если серия была отброшена.