【问题标题】:Parse date from two columns pandas从两列熊猫中解析日期
【发布时间】:2016-06-04 17:17:47
【问题描述】:

我有一组看起来像这样的数据(3 列)。日期和时间在 1 列,时区在另一列。

location,time,zone
EASTERN HILLSBOROUGH,1/27/2015 12:00,EST-5
EASTERN HILLSBOROUGH,1/24/2015 7:00,EST-5
EASTERN HILLSBOROUGH,1/27/2015 6:00,EST-5
EASTERN HILLSBOROUGH,2/14/2015 8:00,EST-5
EASTERN HILLSBOROUGH,2/7/2015 22:00,EST-5
EASTERN HILLSBOROUGH,2/2/2015 2:00,EST-5

我使用pandas 来解析日期和时间及其各自的时区。在read_csv 我可以做parse_dates = [[1,2]],根据docs,将列组合成1并解析它们。

所以现在新数据看起来像这样(2 列)

location,time_zone
EASTERN HILLSBOROUGH,1/27/2015 12:00 EST-5
EASTERN HILLSBOROUGH,1/24/2015 7:00 EST-5
EASTERN HILLSBOROUGH,1/27/2015 6:00 EST-5
EASTERN HILLSBOROUGH,2/14/2015 8:00 EST-5
EASTERN HILLSBOROUGH,2/7/2015 22:00 EST-5
EASTERN HILLSBOROUGH,2/2/2015 2:00 EST-5

但是,如果我输入 df['time_zone'].dtype,我会得到 dtype('O'),它不是 datetimelike,因为我不能使用 dt 访问器。

我还能如何正确解析这两列?

【问题讨论】:

  • 这有帮助吗,看起来他有同样的dtype('O') 问题。 df['time_zone'] = pd.to_datetime(df['time_zone'])stackoverflow.com/a/24446716/5889975
  • @steven 给了我ValueError: Unknown string format。熊猫出于某种原因不喜欢这种格式,可能的错误? datetime 也不喜欢它,但 dateutil 工作正常。我尝试在映射函数中使用它,但给了我与上面相同的ValueError
  • 你从中得到了什么结果:type(df.time_zone.iat[0])?这会查看特定值而不是整个列类型。
  • @Alexander 这是str
  • df.zone.unique() 的值是多少?

标签: python pandas date datetime datetime-parsing


【解决方案1】:

不确定这是否是您想要的,但您可以直接读取(无需任何日期时间解析)然后使用 to_datetime(注意新变量 time_zone 比时间晚 5 小时)。

df['time_zone'] = pd.to_datetime( df.time + df.zone )

               location             time   zone           time_zone
0  EASTERN HILLSBOROUGH  1/27/2015 12:00  EST-5 2015-01-27 17:00:00
1  EASTERN HILLSBOROUGH   1/24/2015 7:00  EST-5 2015-01-24 12:00:00
2  EASTERN HILLSBOROUGH   1/27/2015 6:00  EST-5 2015-01-27 11:00:00
3  EASTERN HILLSBOROUGH   2/14/2015 8:00  EST-5 2015-02-14 13:00:00
4  EASTERN HILLSBOROUGH   2/7/2015 22:00  EST-5 2015-02-08 03:00:00
5  EASTERN HILLSBOROUGH    2/2/2015 2:00  EST-5 2015-02-02 07:00:00

df.info()

location     6 non-null object
time         6 non-null object
zone         6 non-null object
time_zone    6 non-null datetime64[ns]

【讨论】:

  • 我已经尝试过了,但是当我这样做时,我仍然得到ValueError: Unknown string format
  • 我不知道,我的意思是,我只是在您提供的数据上运行了它,它对我来说工作正常。熊猫 0.17.1 在这里。使用我提供的代码,您可以检查问题是否出在时间或区域部分。即尝试'1/1/2015 12:00' + df.zonedf.time + 'EST-5' 看看哪个部分产生了错误
  • 同一个pandas版本,python和dateutil呢?如果你不介意的话。
  • 我在 python 3.5.1。不确定 dateutil 但我最近更新了 anaconda 所以可能是最近的版本。
  • 好的,现在可以了。不知道为什么会这样,因为数据没有问题,但添加 errors = 'coerce' 运行良好。我检查了我的任何行是否有 NaT 输出,但没有。
【解决方案2】:

根据pytz module

处理时间的首选方式是始终使用 UTC, 仅在生成要读取的输出时转换为本地时间 人类。

我不相信您的时区是标准的,这使得转换更加棘手。但是,我们应该能够去除时区偏移,并使用datetime.timedelta 将其添加到 UTC 时间。这是一个 hack,我希望我知道一个更好的方法。

我假设所有时间都记录在当地时区,因此 1/27/2015 12:00 EST-5 将是 1/27/2015 17:00 UTC。

from pytz import utc
import datetime as dt

df = pd.read_csv('times.csv')
df['UTC_time'] = [utc.localize(t) - dt.timedelta(hours=int(h)) 
                  for t, h in zip(pd.to_datetime(df.time), 
                                  df.zone.str.extract(r'(-?\d+)'))]

>>> df
               location             time   zone                  UTC_time
0  EASTERN HILLSBOROUGH  1/27/2015 12:00  EST-5 2015-01-27 17:00:00+00:00
1  EASTERN HILLSBOROUGH   1/24/2015 7:00  EST-5 2015-01-24 12:00:00+00:00
2  EASTERN HILLSBOROUGH   1/27/2015 6:00  EST-5 2015-01-27 11:00:00+00:00
3  EASTERN HILLSBOROUGH   2/14/2015 8:00  EST-5 2015-02-14 13:00:00+00:00
4  EASTERN HILLSBOROUGH   2/7/2015 22:00  EST-5 2015-02-08 03:00:00+00:00
5  EASTERN HILLSBOROUGH    2/2/2015 2:00  EST-5 2015-02-02 07:00:00+00:00

检查单个时间戳,您会注意到时区设置为 UTC:

>>> df.UTC_time.iat[0]
Timestamp('2015-01-27 17:00:00+0000', tz='UTC')

>>> df.UTC_time.iat[0].tzname()
'UTC'

在不同的时区显示它们:

fmt = '%Y-%m-%d %H:%M:%S %Z%z'
>>> [t.astimezone('EST').strftime(fmt) for t in df.UTC_time]
['2015-01-27 12:00:00 EST-0500',
 '2015-01-24 07:00:00 EST-0500',
 '2015-01-27 06:00:00 EST-0500',
 '2015-02-14 08:00:00 EST-0500',
 '2015-02-07 22:00:00 EST-0500',
 '2015-02-02 02:00:00 EST-0500']

这是一个测试。让我们更改df 中的时区,看看其他解决方案是否仍然有效:

df['zone'] = ['EST-5', 'CST-6', 'MST-7', 'GST10', 'PST-8', 'AKST-9']
df['UTC_time'] = [utc.localize(t) - dt.timedelta(hours=int(h)) 
                  for t, h in zip(pd.to_datetime(df.time), 
                                  df.zone.str.extract(r'(-?\d+)'))]
>>> df
               location             time    zone                  UTC_time
0  EASTERN HILLSBOROUGH  1/27/2015 12:00   EST-5 2015-01-27 17:00:00+00:00
1  EASTERN HILLSBOROUGH   1/24/2015 7:00   CST-6 2015-01-24 13:00:00+00:00
2  EASTERN HILLSBOROUGH   1/27/2015 6:00   MST-7 2015-01-27 13:00:00+00:00
3  EASTERN HILLSBOROUGH   2/14/2015 8:00   GST10 2015-02-13 22:00:00+00:00
4  EASTERN HILLSBOROUGH   2/7/2015 22:00   PST-8 2015-02-08 06:00:00+00:00
5  EASTERN HILLSBOROUGH    2/2/2015 2:00  AKST-9 2015-02-02 11:00:00+00:00

查看python docs 了解有关时间处理的更多详细信息。

这是一篇关于该主题的优秀 SO 文章。 How to make an unaware datetime timezone aware in python

这里是 tz 数据库时区的link

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-02-20
    • 2018-04-22
    • 2019-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多