【问题标题】:Getting error "ValueError: time data '' does not match format '%Y-%m-%d %H:%M:%S'"出现错误“ValueError:时间数据''与格式'%Y-%m-%d %H:%M:%S'不匹配”
【发布时间】:2020-01-09 20:30:11
【问题描述】:

这是 df 的示例:

pId tPS                 tLL                 dZ
129 2019-12-02 15:04:09 2019-12-02 15:06:31 5f723
129 2019-12-02 15:04:15 2019-12-02 15:06:37 5f723
129 2019-12-02 15:05:15 2019-12-02 15:07:37 5f723
129 2019-12-02 15:05:18 2019-12-02 15:07:40 5f723
129 2019-12-02 15:05:24 2019-12-02 15:07:46 5f723

pID 是一个人的 ID,我正在尝试检查每个 ID 的进入、退出和持续时间。

代码如下:

from datetime import datetime
stats=df.sort_values(by=['pId', 'tPS', 'tLL'])[['pId', 'tPS', 'tLL', 'dZ']]
pid = ''
enter_t = ''
exit_t = ''

enter_exit_times=[]

for ind, row in stats.iterrows():

    if pid =='':
        enter_t = row['tPS']
        print(enter_t)

    if row['pId']!= pid or ((datetime.strftime(row['tLL'], "%Y-%m-%d %H:%M:%S") 
                         - datetime.strftime(exit_t, "%Y-%m-%d %H:%M:%S")).total_seconds()>2*60*60):

    duration = (datetime.strptime(exit_t, "%Y-%m-%d %H:%M:%S") -
                datetime.strptime(enter_t, "%Y-%m-%d %H:%M:%S"))

    enter_exit_times.append([pid, enter_t, exit_t, duration.total_seconds()])

    pid = row['pId']

    enter_t = row['tPS']

enter_exit_times.append([pid, enter_t, exit_t])
enter_exit_times_df = pd.DataFrame(enter_exit_times)

所以这里

  • pid 是 id
  • enter_t是进入时间
  • exit_t是退出时间
  • tPS是时候了
  • tLL 是休息时间。

然后我正在创建一个列表,我在下面编写一个循环。最初,我通过for 循环运行它,在该循环中迭代数据框的行。所以有两个if 循环,一个带有pid,其中一个空值意味着它需要采用row[tPS],如果没有,那么它必须通过not 循环。然后我计算持续时间,然后将值附加到进出时间。

我收到此错误:

2019-12-02 15:04:09
---------------------------------------------------------------------------
ValueError                           Traceback (most recent callast)
<ipython-input-411-fd8f6f998cc8> in <module>
12     if row['pId']!= pid or ((datetime.strftime(row['tLL'], "%Y-%m-%d %H:%M:%S") 
13                              - datetime.strftime(exit_t, "%Y-%m-%d %H:%M:%S")).total_seconds()>2*60*60):
---> 14         duration = (datetime.strptime(exit_t, "%Y-%m-%d %H:%M:%S") -
15                     datetime.strptime(enter_t, "%Y-%m-%d %H:%M:%S"))
16         enter_exit_times.append([pid, enter_t, exit_t, duration.total_seconds()])

~/opt/anaconda3/lib/python3.7/_strptime.py in _strptime_datetime(cls, data_string, format)
575     """Return a class cls instance based on the input string and the
576     format string."""
--> 577     tt, fraction, gmtoff_fraction = _strptime(data_string, format)
578     tzname, gmtoff = tt[-2:]
579     args = tt[:6] + (fraction,)

~/opt/anaconda3/lib/python3.7/_strptime.py in _strptime(data_string, format)
357     if not found:
358         raise ValueError("time data %r does not match format %r" %
--> 359                          (data_string, format))
360     if len(data_string) != found.end():
361         raise ValueError("unconverted data remains: %s" %

**ValueError: time data '' does not match format '%Y-%m-%d %H:%M:%S'**

【问题讨论】:

  • 尝试分解你的代码。老实说,我觉得你甚至可能不理解你自己在那里使用的代码。分解它,然后尝试找出问题,以便您可以发布更详细的问题。下一次,贴一些代码,不要让我们做所有的努力。
  • 显示df内容,提供minimal reproducible example
  • 我建议在duration = ... 行之前打印出enter_texit_t 的值。然后检查它是否与传递给strptime 的日期时间格式匹配。

标签: python python-3.x dataframe python-datetime


【解决方案1】:

错误的原因是exit_t没有在循环中设置anywhere。它是一个空字符串。您在循环之前将其设置为exit_t = '',但之后它就再也不会设置了。这就是strptime 在这里抛出错误的原因:

>>> datetime.strptime(' ', "%Y-%m-%d %H:%M:%S")
Traceback (most recent call last):
...
  File "/usr/local/Cellar/python/3.7.6/Frameworks/Python.framework/Versions/3.7/lib/python3.7/_strptime.py", line 359, in _strptime
    (data_string, format))
ValueError: time data ' ' does not match format '%Y-%m-%d %H:%M:%S'

解决方案是将其正确设置为"tLL"(如果我理解正确的话)。

但我想更进一步地说,我认为您正在使代码变得比它应该的复杂得多。我的理解是你只想计算"tPS"(时间)和"tLL"(时间)之间的持续时间。由于您已经在遍历每一行,因此您只需要适当地分配值

pid = row['pId']

enter_t_str = row['tPS']  # strings
exit_t_str = row['tLL']   # strings

然后使用strptime将日期时间字符串转换为日期时间对象

enter_t_dt = datetime.strptime(enter_t_str, "%Y-%m-%d %H:%M:%S")
exit_t_dt = datetime.strptime(exit_t_str, "%Y-%m-%d %H:%M:%S")

然后计算持续时间

duration = exit_t_dt - enter_t_dt

然后最后将其附加到您的列表中

enter_exit_times.append([pid, enter_t_str, exit_t_str, duration.total_seconds()])

无需跟踪"pId"

这是完整的代码:

stats = df.sort_values(by=['pId', 'tPS', 'tLL'])[['pId', 'tPS', 'tLL', 'dZ']]

pid = ''
enter_t = ''
exit_t = ''
enter_exit_times = []

for ind, row in stats.iterrows():
    pid = row['pId']

    enter_t_str = row['tPS']
    exit_t_str = row['tLL']

    enter_t_dt = datetime.strptime(enter_t_str, "%Y-%m-%d %H:%M:%S")
    exit_t_dt = datetime.strptime(exit_t_str, "%Y-%m-%d %H:%M:%S")
    duration = exit_t_dt - enter_t_dt

    enter_exit_times.append([pid, enter_t_str, exit_t_str, duration.total_seconds()])

enter_exit_times_df = pd.DataFrame(enter_exit_times)
print(enter_exit_times_df)

以及输出DataFrame:

     0                    1                    2      3
0  129  2019-12-02 15:04:09  2019-12-02 15:06:31  142.0
1  129  2019-12-02 15:04:15  2019-12-02 15:06:37  142.0
2  129  2019-12-02 15:05:15  2019-12-02 15:07:37  142.0
3  129  2019-12-02 15:05:18  2019-12-02 15:07:40  142.0
4  129  2019-12-02 15:05:24  2019-12-02 15:07:46  142.0

如果您只想获取一天中特定时间段的进入/退出时间,您可以为开始和结束时间创建 datetime 对象,并定期进行比较:

>>> dt_beg = datetime(2019,12,2,8,0,0)   #8AM
>>> dt_beg
datetime.datetime(2019, 12, 2, 8, 0)
>>> dt_end = datetime(2019,12,2,10,0,0)  #10AM
>>> dt_end
datetime.datetime(2019, 12, 2, 10, 0)
>>> dt = datetime(2019,12,2,9,34,0)      #9:34AM
>>> dt_beg < dt < dt_end
True
>>> dt = datetime(2019,12,2,14,34,0)     #2:34PM
>>> dt_beg < dt < dt_end
False

因此,您可以添加过滤器以将要附加到 enter_exit_times 的内容添加:

if (enter_t_dt > start_dt and exit_t_dt < end_dt):
    enter_exit_times.append(...)

【讨论】:

  • 这非常清楚...非常感谢。 ..但是我们是否有可能每天在特定时间过滤它.. 可能像早上 8 点到 10 点,然后查看每个 PID 在每天该时间之间花费的持续时间?
  • @ghost22111 是的,你可以。 datetime 对象可以像常规数字一样相互比较。您可以设置开始时间和结束时间,然后检查enter_t_dt 是否在开始时间之后,exit_t_dt 是否在结束时间之前。请参阅我的更新答案。
猜你喜欢
  • 2016-10-15
  • 1970-01-01
  • 1970-01-01
  • 2017-06-04
  • 2022-01-20
  • 1970-01-01
  • 1970-01-01
  • 2021-10-11
  • 2019-05-24
相关资源
最近更新 更多