问题描述
我从在线API收集了一系列数据点,每个数据点都有一个值和一个ISO时间戳。不幸的是,我需要遍历它们,因此我将它们存储在临时dict
中,然后从中创建一个熊猫数据框,并将索引设置为timestamp列(简化示例):
from datetime import datetime
import pandas
input_data = [
'2019-09-16T06:44:01+02:00','2019-11-11T09:13:01+01:00',]
data = []
for timestamp in input_data:
_date = datetime.fromisoformat(timestamp)
data.append({'time': _date})
pd_data = pandas.DataFrame(data).set_index('time')
只要所有时间戳都在同一时区和 DST /非DST中,一切就可以正常工作,并且,我得到了一个带有DatetimeIndex
的数据框,以后可以使用。
但是,一旦两个不同的时间偏移出现在一个数据集中(上例),我在数据框中只会得到一个Index
,它不支持任何基于时间的方法。
有什么方法可以使大熊猫接受时区感知的,不同的日期作为索引?
解决方法
- 大熊猫
datetime
列也要求偏移量相同。具有不同偏移量的列将不会转换为datetime
dtype。 - 我建议在将数据转换为大熊猫之前,不要将其转换为日期时间。
- 分隔时间偏移,并将其视为
timedelta
-
to_timedelta
要求格式为'hh:mm:ss'
,因此在偏移量的末尾添加':00'
- 有关所有可用的timedelta操作,请参见Pandas: Time deltas
-
pandas.Series.dt.tz_convert
-
pandas.Series.tz_localize
- 使用以下方法转换为特定的TZ:
- 如果日期时间不是
datetime64[ns,UTC]
dtype,请先在.dt.tz_localize('UTC')
之前使用.dt.tz_convert('US/Pacific')
- 否则,
df.datetime_utc.dt.tz_convert('US/Pacific')
- 如果日期时间不是
import pandas as pd
# sample data
input_data = ['2019-09-16T06:44:01+02:00','2019-11-11T09:13:01+01:00']
# dataframe
df = pd.DataFrame(input_data,columns=['datetime'])
# separate the offset from the datetime and convert it to a timedelta
df['offset'] = pd.to_timedelta(df.datetime.str[-6:] + ':00')
# if desired,create a str with the separated datetime
# converting this to a datetime will lead to AmbiguousTimeError because of overlapping datetimes at 2AM,per the OP
df['datetime_str'] = df.datetime.str[:-6]
# convert the datetime column to a datetime format without the offset
df['datetime_utc'] = pd.to_datetime(df.datetime,utc=True)
# display(df)
datetime offset datetime_str datetime_utc
0 2019-09-16T06:44:01+02:00 0 days 02:00:00 2019-09-16 06:44:01 2019-09-16 04:44:01+00:00
1 2019-11-11T09:13:01+01:00 0 days 01:00:00 2019-11-11 09:13:01 2019-11-11 08:13:01+00:00
print(df.info())
[out]:
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 2 entries,0 to 1
Data columns (total 4 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 datetime 2 non-null object
1 offset 2 non-null timedelta64[ns]
2 datetime_str 2 non-null object
3 datetime_utc 2 non-null datetime64[ns,UTC]
dtypes: datetime64[ns,UTC](1),object(2),timedelta64[ns](1)
memory usage: 192.0+ bytes
# convert to local timezone
df.datetime_utc.dt.tz_convert('US/Pacific')
[out]:
0 2019-09-15 21:44:01-07:00
1 2019-11-11 00:13:01-08:00
Name: datetime_utc,dtype: datetime64[ns,US/Pacific]
其他资源
- Calculate Pandas DataFrame Time Difference Between Two Columns in Hours and Minutes。
- Talk Python to Me: Episode #271: Unlock the mysteries of time,Python's datetime that is!
- Real Python: Using Python datetime to Work With Dates and Times
-
dateutil
模块提供了对标准datetime
模块的强大扩展。
对问题的措辞进行较小的更正(我认为这很重要)。您所拥有的就是UTC偏移量-DST / no-DST会需要比这更多的 信息,即时区。在这里,这一点很重要,因为您可以轻松地将带有UTC偏移量(甚至不同)的UTC偏移量解析为时间戳:
import pandas as pd
input_data = [
'2019-09-16T06:44:01+02:00','2019-11-11T09:13:01+01:00',]
dti = pd.to_datetime(input_data,utc=True)
# dti
# DatetimeIndex(['2019-09-16 04:44:01+00:00','2019-11-11 08:13:01+00:00'],dtype='datetime64[ns,UTC]',freq=None)
我总是更喜欢与UTC合作,所以我会满意的。但是,如果您确实需要某个时区的日期时间,则可以将其转换为
dti = dti.tz_convert('Europe/Berlin')
# dti
# DatetimeIndex(['2019-09-16 06:44:01+02:00','2019-11-11 09:13:01+01:00'],Europe/Berlin]',freq=None)
,
我不知道使用时区感知日期时间作为索引并以熊猫为单位获取日期时间索引的方法。我确实有一个建议,可能会有所帮助,具体取决于您的数据所需的内容。
将datetime对象转换为相同的时区是否可以接受,还是必须保留时区信息?如果确实需要时区,但不一定需要索引,则在遍历日期时,您可以将新列与旧时区一起存储,或者将时区中的原始时间复制到新列中,以便仍然可以访问它。