我有一些持续时间类型数据(单圈时间)为
pl.String
,无法使用strptime
进行转换,而常规日期时间按预期工作。
分钟(在 :) 之前和秒(在 . 之前)始终填充为两位数,毫秒始终 3 位数字。
单圈时间总是< 2 min.
df = pl.DataFrame({
"lap_time": ["01:14.007", "00:53.040", "01:00.123"]
})
df = df.with_columns(
# pl.col('release_date').str.to_date("%B %d, %Y"), # works
pl.col('lap_time').str.to_time("%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
部分的某些奇怪行为?
如果您的持续时间可能超过 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").list.get(0),
seconds=pl.col("time").list.get(1),
milliseconds=pl.col("time").list.get(2)
).alias("time")
)
┌──────────────┐
│ time │
│ --- │
│ duration[ns] │
╞══════════════╡
│ 1m 14s 7ms │
│ 1h 40m 20s │
│ -5m │
└──────────────┘
pl.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.to_time("%T%.3f")
.cast(pl.Duration)
)
┌───────────┬──────────────┐
│ str_time ┆ duration │
│ --- ┆ --- │
│ str ┆ duration[μs] │
╞═══════════╪══════════════╡
│ 01:14.007 ┆ 1m 14s 7ms │
│ 01:18.880 ┆ 1m 18s 880ms │
└───────────┴──────────────┘
创建您自己的解析器 -
strptime
仅适用于日期时间戳,不适用于时间增量。接受的答案是不好的做法,因为它对于合理的输入(例如 80 分钟的持续时间或负持续时间)会失败。
pl.Series.str.extract()
制作自己的正则表达式解析器,并在将它们传递到 Duration
构造函数之前提取所需的值。
据我所知,Rust 中没有“持续时间标记”解析器。如果有人正在读这篇文章,也许放一个板条箱是个好主意。语法可能与
strptime
类似,但处理以下情况:负持续时间、最重要的“数字”/子单位不换行,在这种情况下,如果它是“分钟持续时间标记”,您将在 60 处换行秒,而不是分钟。特别是确保 61 仍然是 61。
代码改编自glebcom的答案:
df = df.with_columns(
# pl.col('release_date').str.to_date("%B %d, %Y"), # works
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'),
)
此答案作为 edit 发布到问题 Trouble with strptime() conversion ofuration time string 由 OP Dorian 根据 CC BY-SA 4.0 发布。