从两列解析日期 pandas

Parse date from two columns pandas

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

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 访问器。

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

不确定这是否是您想要的,但您可以只读入(不进行任何日期时间解析)然后使用 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]

根据 pytz module:

The preferred way of dealing with times is to always work in UTC, converting to localtime only when generating output to be read by humans.

我不相信你的时区是标准的,这使得转换有点棘手。然而,我们应该能够去除时区偏移量并使用 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