Rust Polars中如何基于UInt32Type与RevMapping创建CategoricalChunked
问题
现有代码已经可以获取CategoricalChunked对应的整数表示与反向映射表(revmap),实现如下:
let s = Series::new("Fruit", ["Apple", "Apple", "Pear"]); let s_cat = s.cast(&DataType::Categorical(Some(Arc::new(RevMapping::default())))).unwrap(); let s_cat_chunck = s_cat.categorical().unwrap().to_owned(); // 拿到CategoricalChunked实例 let s_logical = s_cat_chunck.logical().to_owned(); // 拿到分类值对应的整数表示 let s_revmap = s_cat_chunck.get_rev_map().to_owned(); // 拿到反向映射表revmap
需要解决的问题:如何基于上述获取到的s_logical与s_revmap创建CategoricalChunked?
问题背景
需要对CategoricalChunked的元素执行大量运算,主要包含比较运算、以及基于比较结果的条件分支判断。待处理的CategoricalChunked数据规模大,算法流程中涉及的比较操作量级极高。目前遍历CategoricalChunked可以调用iter_str()方法,但该迭代器返回元素为&str类型,字符串比较操作性能较差,因此计划直接基于整数表示s_logical执行比较运算,处理完成后再将结果转换回Categorical类型。
解决方案
直接调用Polars内置的CategoricalChunked::from_cats_and_rev_map关联方法即可完成构造,无需手动做编码映射转换。
方法参数要求:
- 第一个参数传入完成运算后的
s_logical:必须是UInt32类型的ChunkedArray,和Categorical类型默认的物理存储类型一致 - 第二个参数传入反向映射表:用
Arc包裹你提前拿到的s_revmap即可,匹配Categorical类型的内存布局要求 - 第三个参数为
is_enum标记:普通Categorical类型传false,Enum类型传true,取值和原始CategoricalChunked的对应属性保持一致即可 - 第四个参数为自定义排序信息:未配置自定义分类排序规则时直接传
None - 第五个参数为全局字典缓存:本地单机场景下构造直接传
None
参考实现代码:
use std::sync::Arc; use polars::prelude::*; // 基于处理完成的整数逻辑数组、原反向映射表重建CategoricalChunked let rebuilt_cat_chunked: CategoricalChunked = CategoricalChunked::from_cats_and_rev_map( s_logical, Arc::new(s_revmap), false, None, None ).unwrap(); // 若需要转回Series类型,直接调用into_series方法即可 let rebuilt_series: Series = rebuilt_cat_chunked.into_series();
性能提示
- 直接操作物理整数数组的优化思路完全可行:u32数值比较是CPU原生支持的单指令操作,性能远高于
iter_str()返回的&str字符串比较,在高量级比较场景下可以带来数量级的性能提升 - 运算过程中不要修改revmap内的编码-字符串映射关系,只要整数值和revmap的映射关系和原数据一致,重建后的分类值就不会出现错乱
- 同字典来源的多个CategoricalChunked做联合运算时,可以共用同一个Arc包裹的revmap实例,避免重复拷贝映射表带来额外内存开销
内容的提问来源于stack exchange,提问作者Kushdesh
相关产品推荐
相关产品推荐

