You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Polars中将数值列格式化为HH:MM:SS及HH:MM:SS.0格式?

如何在Polars中将数值列格式化为HH:MM:SS及HH:MM:SS.0格式?

嗨,我来帮你搞定这个问题!你之前的代码没成功,是因为犯了个小错误——把结构体对象转成字符串传给timedelta的seconds参数了,timedelta要的是数值,不是字符串哦。下面给你几个靠谱的解决办法:

方法一:修正你的map_elements写法(简单直观)

如果你还是想用map_elements,只需要调整参数的获取方式,直接取出秒数值传给timedelta就行。另外如果需要区分整数秒和带小数秒的显示格式,也可以加个判断:

from datetime import timedelta
import polars as pl

df = pl.DataFrame({"seconds": [1.0, 4562.2, 2.44, 123.567]})

# 修正后的写法,自动处理整数/小数秒的显示
df = df.with_columns(
    hhmmss=pl.col("seconds").map_elements(
        lambda sec: str(timedelta(seconds=sec)).split(".")[0] if sec.is_integer() 
        else f"{timedelta(seconds=sec):.3f}"
    )
)

print(df)

运行后会得到:

shape: (4, 2)
┌──────────┬─────────────┐
│ seconds  ┆ hhmmss      │
│ ---      ┆ ---         │
│ f64      ┆ str         │
╞══════════╪═════════════╡
│ 1.0      ┆ 0:00:01     │
│ 4562.2   ┆ 1:16:02.200 │
│ 2.44     ┆ 0:00:02.440 │
│ 123.567  ┆ 0:02:03.567 │
└──────────┴─────────────┘

要是你想统一显示两位小时(比如00:00:01),可以把格式化逻辑改成字符串拼接补零的方式,比如:

def format_sec(sec):
    td = timedelta(seconds=sec)
    hours, remainder = divmod(td.total_seconds(), 3600)
    minutes, seconds = divmod(remainder, 60)
    if sec.is_integer():
        return f"{int(hours):02d}:{int(minutes):02d}:{int(seconds):02d}"
    else:
        return f"{int(hours):02d}:{int(minutes):02d}:{seconds:06.3f}"

df = df.with_columns(hhmmss=pl.col("seconds").map_elements(format_sec))

这样输出的小时就是两位的格式啦。

方法二:用Polars内置函数(高效推荐)

map_elements是逐行处理数据,数据量大的时候效率会比较低。更推荐用Polars的向量化时间函数,直接把秒数转成Duration类型再格式化,速度快很多:

import polars as pl

df = pl.DataFrame({"seconds": [1.0, 4562.2, 2.44, 123.567]})

# 把秒数转成纳秒(Polars的Duration基于纳秒),再转成Duration类型
df = df.with_columns(
    duration=pl.col("seconds") * 1_000_000_000
).with_columns(
    # 格式化时间,分两种情况处理
    hhmmss=pl.when(pl.col("seconds").is_integer())
           .then(pl.col("duration").cast(pl.Duration).dt.to_string("%H:%M:%S"))
           .otherwise(pl.col("duration").cast(pl.Duration).dt.to_string("%H:%M:%S.%f").str.slice(0, 12))
).drop("duration")

print(df)

这个方法会输出统一的两位小时格式:

shape: (4, 2)
┌──────────┬─────────────┐
│ seconds  ┆ hhmmss      │
│ ---      ┆ ---         │
│ f64      ┆ str         │
╞══════════╪═════════════╡
│ 1.0      ┆ 00:00:01    │
│ 4562.2   ┆ 01:16:02.200│
│ 2.44     ┆ 00:00:02.440│
│ 123.567  ┆ 00:02:03.567│
└──────────┴─────────────┘

最后说下你之前代码的问题

你原来的代码里用pl.struct('seconds').map_elements(lambda x: str(timedelta(seconds = str(x)))),这里的x是一个结构体对象,str(x)会变成类似{'seconds': 1.0}的字符串,传给timedelta肯定会报错。哪怕改成x['seconds'],也不需要转成字符串,直接传数值就行。不过还是更推荐上面的方法二,效率更高~

备注:内容来源于stack exchange,提问作者frank

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.13 18:39:27