在 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))
但我不知道如何将自定义排序包含在内。
我还检查了在极坐标中,我可以自己创建一个带有级别的分类类型吗?,但我不想在我的数据框中添加另一列仅用于排序。
说你有
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 │
└──────┴──────┘
来自文档: 用途:
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"])
Polars pl.Enum
中添加了
0.20.0
类型来处理此类情况。
my_order = ["k", "z", "b", "a"]
df.with_columns(pl.col("cats").cast(pl.Enum(my_order)))
shape: (5, 2)
┌──────┬──────┐
│ cats ┆ vals │
│ --- ┆ --- │
│ enum ┆ i64 │
╞══════╪══════╡
│ z ┆ 3 │
│ z ┆ 1 │
│ k ┆ 2 │
│ a ┆ 2 │
│ b ┆ 3 │
└──────┴──────┘
检查/验证订单:
(df.with_columns(pl.col("cats").cast(pl.Enum(my_order)))
.sort("cats")
.with_columns(order = pl.col("cats").to_physical())
)
shape: (5, 3)
┌──────┬──────┬───────┐
│ cats ┆ vals ┆ order │
│ --- ┆ --- ┆ --- │
│ enum ┆ i64 ┆ u32 │
╞══════╪══════╪═══════╡
│ k ┆ 2 ┆ 0 │
│ z ┆ 3 ┆ 1 │
│ z ┆ 1 ┆ 1 │
│ b ┆ 3 ┆ 2 │
│ a ┆ 2 ┆ 3 │
└──────┴──────┴───────┘