如何修改Polars DataFrame中已有分类列的自定义排序?
修改Polars DataFrame分类列自定义排序的解决方案
问题原因
你遇到的问题核心是Polars的StringCache会缓存首次注册的分类顺序:第一次通过pl.Series(myorder).cast(pl.Categorical)在缓存中注册了["k", "z", "b", "a"]的类别映射,后续再次执行cast(pl.Categorical)时,Polars会直接复用已缓存的映射关系,导致新的排序规则不生效。
解决方案
推荐以下两种可靠的修改方式:
方法1:显式指定分类顺序(推荐,无需依赖缓存)
直接在cast(pl.Categorical)时通过order参数指定新的排序,同时先将原分类列转回字符串类型,确保完全重置类别映射:
# 新的自定义排序 myorder = ["b", "z", "k", "a"] # 先转回字符串,再重新设置分类并指定顺序 df = df.with_columns( pl.col('cats').cast(pl.String).cast(pl.Categorical(order=myorder)) ) print(df.sort(["cats"]))
执行后输出会符合新排序:
shape: (5, 2) ┌──────┬──────┐ │ cats ┆ vals │ │ --- ┆ --- │ │ cat ┆ i64 │ ╞══════╪══════╡ │ b ┆ 3 │ │ z ┆ 3 │ │ z ┆ 1 │ │ k ┆ 2 │ │ a ┆ 2 │ └──────┴──────┘
方法2:清空StringCache后重新注册
如果需要保留缓存方式,需先清空已有缓存,再重新注册新排序,同时将列转回字符串后再cast:
# 新的自定义排序 myorder = ["b", "z", "k", "a"] # 清空字符串缓存 pl.StringCache().clear() with pl.StringCache(): # 重新注册新的分类顺序 pl.Series(myorder).cast(pl.Categorical) # 先转回字符串再转换为分类,避免复用旧映射 df = df.with_columns(pl.col('cats').cast(pl.String).cast(pl.Categorical)) print(df.sort(["cats"]))
注意事项
- Polars 0.18.0及以上版本支持
pl.Categorical(order=...)参数,这是更直观且可控的方式,优先使用。 - 不要直接对已有分类列再次执行
cast(pl.Categorical),因为Polars会复用缓存或已有列的类别映射,无法更新排序。
内容的提问来源于stack exchange,提问作者SenseiH
相关产品推荐
相关产品推荐

