【问题标题】:ValueError: time data '10/11/2006 24:00' does not match format '%d/%m/%Y %H:%M'ValueError: 时间数据 '10/11/2006 24:00' 与格式 '%d/%m/%Y %H:%M' 不匹配
【发布时间】:2018-10-07 22:36:04
【问题描述】:

我试过了:

df["datetime_obj"] = df["datetime"].apply(lambda dt: datetime.strptime(dt, "%d/%m/%Y %H:%M"))

但出现此错误:

ValueError: 时间数据 '10/11/2006 24:00' 与格式不匹配 '%d/%m/%Y %H:%M'

如何正确解决?

【问题讨论】:

  • 24:00 不是有效小时。
  • %H的范围是0 <= h < 24。
  • 您最初是如何获得这些值的?
  • @WillemVanOnsem:这些值来自输入数据,我应该对其进行预处理。有什么办法可以解决这个问题?
  • 那么10/11/2006 24:00 是什么意思?那是11/11/2006 00:00?因为这确实让它变得更加棘手。

标签: python pandas datetime


【解决方案1】:

这不起作用的原因是因为%H 参数只接受00 到23 范围内的值(包括两者)。因此,这意味着 24:00 就像错误所说的那样 - 不是有效的时间字符串。

因此,我认为除了将字符串转换为有效格式外,我们没有太多其他选择。为此,我们可以先将 24:00 替换为 00:00,然后为这些时间戳增加日期。

喜欢:

from datetime import timedelta
import pandas as pd

df['datetime_zero'] = df['datetime'].str.replace('24:00', '0:00')
df['datetime_er'] = pd.to_datetime(df['datetime_zero'], format='%d/%m/%Y %H:%M')
selrow = df['datetime'].str.contains('24:00')
df['datetime_obj'] = df['datetime_er'] + selrow * timedelta(days=1)

因此,最后一行将一天添加到包含 24:00 的行,这样 '10/11/2006 24:00' 就被转换为 '11/11/2006 24:00'。但是请注意,上述内容相当不安全,因为根据时间戳的格式,这将/不会起作用。对于上述情况,它(可能)会起作用,因为只有一个冒号。但是,如果 datetimes 也有秒数,则过滤器可能会为 00:24:00 触发,因此可能需要一些额外的工作才能使其正常工作。

【讨论】:

  • 酷,但我也收到此警告。你知道这意味着什么吗? /opt/conda/lib/python3.6/site-packages/ipykernel_launcher.py:4: SettingWithCopyWarning: 试图在来自 DataFrame 的切片副本上设置值 请参阅文档中的警告:pandas.pydata.org/pandas-docs/stable/…
  • @ScalaBoy:是的,警告有什么不清楚的地方?
  • @ScalaBoy:通过乘法而不是过滤。但不幸的是,这可能会导致额外的低效率,因为您似乎已经使用.apply(..),性能可能已经不是那么大了:)
  • 很好的解释。我觉得你不应该必须替换'24:00' 和也检查str.contains('24:00') 作为单独的步骤。您可以使用布尔系列并重用它。我在回答中尝试了这个。
  • @WillemVanOnsem,明白了,猜猜这比什么都更有风格。
【解决方案2】:

您的数据不遵循 Python / Pandas datetime 对象使用的约定。应该只有一种存储特定datetime 的方法,即'10/11/2006 24:00' 应重写为'11/11/2006 00:00'。

这是解决问题的一种方法:

# find datetimes which have '24:00' and rewrite
twenty_fours = df['strings'].str[-5:] == '24:00'
df.loc[twenty_fours, 'strings'] = df['strings'].str[:-5] + '00:00'

# construct datetime series
df['datetime'] = pd.to_datetime(df['strings'], format='%d/%m/%Y %H:%M')

# add one day where applicable
df.loc[twenty_fours, 'datetime'] += pd.DateOffset(1)

这里有一些数据要测试:

dateList = ['10/11/2006 24:00', '11/11/2006 00:00', '12/11/2006 15:00']
df = pd.DataFrame({'strings': dateList})

上述转换后的结果:

print(df['datetime'])

0   2006-11-11 00:00:00
1   2006-11-11 00:00:00
2   2006-11-12 15:00:00
Name: datetime, dtype: datetime64[ns]

【讨论】:

    【解决方案3】:

    如文档 (https://docs.python.org/2/library/datetime.html#strftime-strptime-behavior) 中所述,小时数从 00 到 23。24:00 即是错误。

    【讨论】:

    • 好的,谢谢。但是我该如何解决这个问题?是否有可能揭示这些案例并将 24 替换为 0?
    • 这是典型的不良数据形式。你有两个选择。要么通过修复生成数据的内容来修复它们(最佳选择),要么通过将 ' 24:' 更改为 ' 00:' 来修复数据(在 Python 中很简单)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-20
    • 2014-09-27
    • 2016-10-15
    • 1970-01-01
    • 1970-01-01
    • 2017-06-04
    • 1970-01-01
    相关资源
    最近更新 更多