我有一些无法使用
strptime
转换的持续时间类型数据(单圈时间),而常规日期时间按预期工作。
在 df 中读取的示例(类型 str
/ pl.Utf8
):
["01:14.007", "01:18.880", ...]
分钟(在 : 之前)和秒(在 . 之前)always 填充到两位数,毫秒是 always 3 位数字。
df = df.with_columns(
[
pl.col('release_date').str.strptime(pl.Date, fmt="%B %d, %Y"), # works
pl.col('lap_time').str.strptime(pl.Time, fmt="%M:%S.%3f").cast(pl.Duration), # fails
]
)
所以我使用了
https://docs.rs/chrono/latest/chrono/format/strftime/index.html中的
chrono
格式说明符定义,它根据polars
的
strptime
文档使用
第二次转换(对于
lap_time
)总是失败,无论我是否使用.%f
,.%3f
,%.3f
。显然,strptime
不允许直接创建 pl.Duration
,所以我尝试使用 pl.Time
但它失败并显示错误:
ComputeError: strict conversion to dates failed, maybe set strict=False
但是设置 strict=False 会产生整个系列的所有
null
值。
我是否遗漏了某些东西或
chrono
或python-polars
部分的一些奇怪行为?
df = df.with_columns(
[
pl.col('release_date').str.strptime(pl.Date, fmt="%B %d, %Y"),
pl.duration(
minutes=pl.col("lap_time").str.slice(0,2),
seconds=pl.col("lap_time").str.slice(3,2),
milliseconds=pl.col("lap_time").str.slice(6,3)
).alias('lap_time'),
]
)
您不能在没有指定时间的情况下使用
pl.Time
。当您将 00
小时添加到您的时间时,代码将起作用:
df = pl.DataFrame({"str_time": ["01:14.007", "01:18.880"]})
df.with_columns(
duration = (pl.lit("00:") + pl.col("str_time"))\
.str.strptime(pl.Time, fmt="%T%.3f")\
.cast(pl.Duration)
)
┌───────────┬──────────────┐
│ str_time ┆ duration │
│ --- ┆ --- │
│ str ┆ duration[μs] │
╞═══════════╪══════════════╡
│ 01:14.007 ┆ 1m 14s 7ms │
│ 01:18.880 ┆ 1m 18s 880ms │
└───────────┴──────────────┘
如果您的 duration 可能超过 24 小时,您可以使用 regex 模式从字符串中提取数据(分钟、秒等):
df = pl.DataFrame({
"time": ["+01:14.007", "100:20.000", "-05:00.000"]
})
df.with_columns(
pl.col("time").str.extract_all(r"([+-]?\d+)")
# /
# you will get array of length 3
# ["min", "sec", "ms"]
).with_columns(
pl.duration(
minutes=pl.col("time").arr.get(0),
seconds=pl.col("time").arr.get(1),
milliseconds=pl.col("time").arr.get(2)
).alias("time")
)
┌──────────────┐
│ time │
│ --- │
│ duration[ns] │
╞══════════════╡
│ 1m 14s 7ms │
│ 1h 40m 20s │
│ -5m │
└──────────────┘
Create your own parser -
strptime
仅适用于日期时间戳,不适用于时间增量。接受的答案是不好的做法,因为它无法用于合理的输入,例如 80 分钟的持续时间或负持续时间。
pl.Series.str.extract()
制作自己的正则表达式解析器,并在将它们传递给 Duration
构造函数之前提取所需的值。
据我所知,Rust 中没有“持续时间戳”解析器。如果有人正在阅读这篇文章,也许是一个板条箱的好主意。语法可能类似于
strptime
但处理以下情况:负持续时间,最重要的“数字”/子单元不换行,在这种情况下,它是“分钟持续时间戳”,您将在 60 秒而不是分钟换行。特别是确保 61 仍然是 61.