Polars如何基于字符串值列表筛选Categorical分类列
Polars Categorical类型列使用字符串值做isin筛选返回空的解决方法
出现这个现象的核心原因是Polars的Categorical类型本质是用整数做物理存储、靠内置字典映射回字符串显示的类型,默认情况下每个Categorical列的字典是独立的,直接给isin()传入裸字符串列表时,Polars不会自动把字符串映射到当前列的分类字典编码,会判定值类型不匹配,最终返回空结果。
注意:直接传入底层整数编码匹配的写法非常不推荐,分类对应的整数编码会随着字典生成顺序、缓存配置变化,很容易出现隐蔽的逻辑错误。
可行的实现方案如下:
- 方案1:将待匹配的字符串列表转为同类型Categorical后传入(性能最优,推荐大数据集使用)
只需要把待匹配的字符串列表先封装为Series、转成Categorical类型,Polars会自动对齐分类映射完成匹配:
运行后会正确返回import polars as pl df = pl.DataFrame({"a": ["foo", "bar", "ham"]}).select(pl.col('a').cast(pl.Categorical)) # 核心是把待匹配值转成Categorical类型 result = df.filter( pl.col("a").isin(pl.Series(["foo"]).cast(pl.Categorical)) )a列值为foo的行。
如果代码里大量用到Categorical类型的匹配,可以开启全局字符串缓存,保证所有Categorical值的编码统一,就不需要每次手动对齐类型:# 开启全局字符串缓存后,所有Categorical的编码映射全局统一 pl.enable_string_cache() df = pl.DataFrame({"a": ["foo", "bar", "ham"]}).select(pl.col('a').cast(pl.Categorical)) # 此时直接转Categorical传入不会出现编码不匹配问题 result = df.filter(pl.col("a").isin(pl.Series(["foo"]).cast(pl.Categorical))) - 方案2:临时将分类列转为字符串类型后匹配(写法最简单,适合小数据集快速开发)
不需要处理类型映射逻辑,直接把目标列临时转成字符串类型再做isin判断,逻辑直观不容易写错:
这个写法的缺点是会损失Categorical类型的性能优势,数据量特别大的时候运行效率比方案1低。result = df.filter( pl.col("a").cast(pl.Utf8).isin(["foo"]) )
内容的提问来源于stack exchange,提问作者supersick
相关产品推荐
相关产品推荐

