Polars中如何正确将十六进制字符串列转换为uint64类型
Polars中十六进制字符串转UInt64的正确实现
问题场景
在Kaggle美国运通违约预测竞赛的公开存储优化方案中,常用操作是将长十六进制格式的ID字符串截取后,按16进制规则解析为uint64类型,大幅降低列存储空间。在Polars中实现该逻辑时通常会遇到两类异常:
- 用
map_elements封装Python原生int(x,16)逻辑,返回结果和正确值接近但末尾数字存在偏差 - 直接截取字符串后调用
cast(pl.UInt64)触发转换错误,传入strict=False时返回空值
错误原因
- 精度丢失:使用
map_elements时如果未显式指定返回类型,Polars会默认将Python函数返回值推断为float64类型。float64仅能精确表示小于2^53的整数,uint64取值范围的大整数会被截断,导致末尾数字错误。 - 解析规则不匹配:Polars默认的字符串转整数逻辑按十进制规则解析,无法识别十六进制包含的a-f字符,因此直接cast会报错。
正确实现
推荐方案(原生高性能,无精度问题)
直接使用Polars字符串命名空间下的整数解析方法,指定16进制解析规则,计算全程在Rust层运行,性能是Python层map_elements的10~100倍,结果完全匹配Python原生计算值:
import polars as pl strings = [ "0000099d6bd597052cdcda90ffabf56573fe9d7c79be5fbac11a8ed792feb62a", "00000fd6641609c6ece5454664794f0340ad84dddce9a267a310b5ae68e9d8e5", ] df = pl.DataFrame({"id": strings}) result = df.with_columns( pl.col("id") .str.slice(-16) # 截取最后16位十六进制字符,对应64bit长度 .str.to_integer(base=16) # 指定按16进制规则解析整数 .cast(pl.UInt64) # 显式转换为无符号64位整数 .alias("parsed_uint64") ) print(result["parsed_uint64"].to_list()) # 输出: [13914591055249847850, 11750091188498716901],与Python原生计算结果完全一致
旧版本兼容方案
如果使用的Polars版本未提供str.to_integer方法,可以通过二进制解码+类型重解释实现:
result = df.with_columns( pl.col("id") .str.slice(-16) .str.decode("hex") # 将十六进制字符串解码为原始二进制 .bin.reinterpret(dtype=pl.UInt64, endianness="big") # 按大端序重解释为uint64 .alias("parsed_uint64") )
注意:十六进制字符串的字节序为大端序,调用
bin.reinterpret时必须显式指定endianness="big",否则会得到字节序反转的错误结果。
内容的提问来源于stack exchange,提问作者TomNorway
相关产品推荐
相关产品推荐

