如何在Polars中将浮点型Unix时间戳高精度转换为Datetime?
解决Polars中字符串格式Unix时间戳转纳秒级Datetime的精度问题
问题根源
直接把字符串时间戳转为Float64会受浮点数精度限制丢失细节,比如1634083172.2470002转成Float64后无法精确存储,乘以1e9计算纳秒时就会出现误差,导致最终Datetime的纳秒部分偏离预期。
最优解决方案:矢量化字符串拆分+整数运算
通过拆分时间戳字符串的整数秒和小数部分,全程用整数运算避免浮点数精度损失,最终拼接出纳秒级精确的Datetime,且适配Polars的大数据处理场景:
import polars as pl df = pl.DataFrame({ "unix_timestamp": ["1634083172.2470002"] }) # 拆分时间戳为秒部分和小数部分,分别处理后合并 df = df.with_columns( pl.col("unix_timestamp").str.split(".").alias("split_ts") ).with_columns( # 秒部分转为秒级Datetime pl.col("split_ts").list.get(0).cast(pl.Int64).cast(pl.Datetime("s")).alias("base_dt"), # 小数部分补零到9位(纳秒长度),转为整数纳秒 pl.col("split_ts").list.get(1).str.pad_end(9, "0").str.slice(0, 9).cast(pl.Int64).alias("ns") ).with_columns( # 合并为纳秒级Datetime (pl.col("base_dt") + pl.col("ns").cast(pl.Duration("ns"))).alias("datetime") ).drop("split_ts", "base_dt", "ns") print(df)
输出结果:
┌────────────────────┬───────────────────────────────┐ │ unix_timestamp ┆ datetime │ │ --- ┆ --- │ │ str ┆ datetime[ns] │ ╞════════════════════╪═══════════════════════════════╡ │ 1634083172.2470002 ┆ 2021-10-12 23:59:32.247000200 │ └────────────────────┴───────────────────────────────┘
小数据量替代方案:结合Decimal库处理
如果数据量不大,也可以用map_elements配合Python的decimal库精确计算总纳秒数:
from decimal import Decimal df = df.with_columns( pl.col("unix_timestamp").map_elements( lambda ts: int(Decimal(ts) * Decimal(1_000_000_000)), return_dtype=pl.Int64 ).cast(pl.Datetime("ns")).alias("datetime") )
注意:map_elements是逐行处理,性能不如矢量化的字符串操作,大数据场景优先选择第一种方案。
内容的提问来源于stack exchange,提问作者elaspog
相关产品推荐
相关产品推荐

