如何根据Polars Decimal类型的scale参数将其转换为Int或Float类型
如何根据Polars Decimal类型的scale参数将其转换为Int或Float类型
嘿,这个问题我刚好碰到过,给你两个实用的解决方案,不管是想读取后批量处理,还是直接让Polars读取时就跳过Decimal类型,都能搞定~
方案一:读取后用polars.selectors批量转换Decimal列
这是最灵活的方式,不用提前了解列的信息,读取完数据后直接对所有Decimal列做批量处理:
- 首先读取你的数据库数据:
import polars as pl from polars import selectors as cs df = pl.read_database("SELECT * FROM your_target_table", connection_uri="your_db_connection_string")
- 用selectors选中所有Decimal类型的列,根据scale判断转成Int或Float:
df_processed = df.with_columns( cs.dtype(pl.Decimal).map( lambda col: pl.when(col.dtype.scale == 0) .then(col.cast(pl.Int64)) # scale为0说明没有小数部分,转成整数 .otherwise(col.cast(pl.Float64)) # 有小数部分就转成浮点数 ) )
这段代码的逻辑很清晰:用cs.dtype(pl.Decimal)精准选中所有Decimal类型的列,然后对每一列检查它的scale参数——如果scale是0(意味着该列的值都是整数),就转成Int64;否则转成Float64。你也可以根据需要调整Int/Float的具体类型(比如用Int32或者Float32)。
方案二:读取时直接指定类型,避免生成Decimal列
如果你不想让Polars在读取时生成Decimal类型的列,可以提前获取数据库表的列信息,手动指定每个列的目标类型:
- 先查询数据库表的列类型(以PostgreSQL为例,其他数据库的信息查询语句略有不同):
with pl.SQLContext() as ctx: ctx.register_connection("db", connection_uri="your_db_connection_string") # 查询目标表的列名和数据类型 table_schema = ctx.execute(""" SELECT column_name, data_type FROM information_schema.columns WHERE table_name = 'your_target_table' """).collect()
- 生成Polars的schema字典,把Decimal/Numeric类型替换成对应的Int或Float:
schema_dict = {} for col_name, data_type in table_schema.rows(): # 匹配Decimal/Numeric类型 if data_type.startswith("numeric") or data_type.startswith("decimal"): # 解析类型中的scale参数,比如"numeric(10,2)"里的2就是scale if "(" in data_type: _, params_part = data_type.split("(", 1) precision, scale = params_part.rstrip(")").split(",") scale = int(scale) schema_dict[col_name] = pl.Int64 if scale == 0 else pl.Float64 else: # 如果没有指定scale,默认转成Float64 schema_dict[col_name] = pl.Float64 else: # 其他类型保持Polars自动推断 schema_dict[col_name] = None
- 读取数据时传入这个schema字典:
df = pl.read_database( "SELECT * FROM your_target_table", connection_uri="your_db_connection_string", schema=schema_dict )
这样读取出来的DataFrame里就不会有Decimal类型的列了,直接是你想要的Int或Float类型~
备注:内容来源于stack exchange,提问作者gkampolis
相关产品推荐
相关产品推荐

