将 ISO 8601 数据的 Pandas 列转换为秒

Convert Pandas Column of ISO 8601 Data to Seconds

我正在尝试将 ISO 8601 持续时间数据的 pandas 数据帧列转换为总秒数。持续时间值看起来像 PT7M7S,这意味着 7 分 7 秒。如果我使用 isodate.parse_duration("PT7M7S") 之类的东西,isodate 0.5.4 可以有效地解析一个字符串。但是,我需要 运行 在 pandas 列上执行相同的命令,但不知道如何操作。我试过 isodate.parse_duration(df2['duration']) 但它 returns 一个 TypeError: Expecting a string.

以下代码创建了一个测试数据帧:

df = ["PT7M7S", "PT7M14S", "PT6M45S"]
df = pd.DataFrame.from_dict(df)
names = df.columns.tolist()
names[names.index(0)] = 'duration'
df.columns = names

这是我试过但无效的代码:

import isodate
dur = isodate.parse_duration(df['duration'])
df['duration'] = dur.total_seconds()

理想的输出是让列 duration 包含对应于该行的总秒数。因此,例如,不是第一行 PT7M7S 而是 427.

感谢任何帮助。谢谢。

您可以使用 str.extract 来解析字符串:

import numpy as np
import pandas as pd

df = pd.DataFrame({'duration': ["PT7M7S", "PT7M14S", "PT6M45S"]})
df[['minutes','seconds']] = df['duration'].str.extract(r'PT(\d+)M(\d+)S', expand=True).astype('int')
df['total_seconds'] = 60*df['minutes'] + df['seconds']

产量

  duration  minutes  seconds  total_seconds
0   PT7M7S        7        7            427
1  PT7M14S        7       14            434
2  PT6M45S        6       45            405

这是一个替代解决方案:

In [53]: (pd.to_datetime(df['duration'], format='PT%MM%SS', errors='coerce') -
    ...:  pd.to_datetime('1900-01-01')).dt.total_seconds()
    ...:
Out[53]:
0    427.0
1    434.0
2    405.0
Name: duration, dtype: float64

数据:

In [54]: df
Out[54]:
  duration
0   PT7M7S
1  PT7M14S
2  PT6M45S

解释:

In [55]: pd.to_datetime(df['duration'], format='PT%MM%SS', errors='coerce')
Out[55]:
0   1900-01-01 00:07:07
1   1900-01-01 00:07:14
2   1900-01-01 00:06:45
Name: duration, dtype: datetime64[ns]

为什么不在系列 df['duration'] 上使用 apply 函数,这样会快得多。

这是一个代码示例。

In [17]: df['duration'] = df['duration'].apply(isodate.parse_duration)
In [18]: df['duration'] = df['duration']/np.timedelta64(1, 's')
In [19]: df
   duration
0     427.0
1     434.0
2     405.0

注意,这里有一个技巧:将datetimetimedelta对象除以不同单位的np.timedelta64,你可以得到这个对象的那个单位的数字。

顺便说一句,如果你有 NaN 或缺失值,你需要处理它们。

另外提一下,unutbu的回答,只适用于你的数据只包含'M''S'的情况。因为 duration_isoformat 可能是 PnnYnnMnnDTnnHnnMnnS.

希望这对你有用。