从 DST 感知日期时间对象在 Dataframe 中创建 pandas DatetimeIndex
Creating pandas DatetimeIndex in Dataframe from DST aware datetime objects
从网上 API 我收集了一系列数据点,每个数据点都有一个值和一个 ISO 时间戳。不幸的是我需要遍历它们,所以我将它们存储在一个临时的 dict
中,然后从中创建一个 pandas 数据帧并将索引设置为时间戳列(简化示例):
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/non-DST 一切正常,而且,我得到一个带有 DatetimeIndex
的数据框,我以后可以继续工作。
但是,一旦两个不同的时间偏移量出现在一个数据集中(上例),我的数据框中只会得到一个 Index
,它不支持任何基于时间的方法。
有什么方法可以让 pandas 接受时区感知、不同日期作为索引?
我不知道使用时区感知日期时间作为索引并在 pandas 中获取日期时间索引的方法。不过,我确实有一个建议可能会有所帮助,具体取决于您对数据的要求。
将日期时间对象转换为同一时区是否可以接受,或者时区信息是否必须保留?如果您确实需要时区但不一定需要索引,在循环遍历日期时,您可以使用旧时区存储一个新列,或者在新列中复制时区的原始时间,以便仍然可以访问它。
- A pandas
datetime
列也要求偏移量相同。具有不同偏移量的列将不会转换为 datetime
dtype。
- 我建议,不要将数据转换为日期时间,直到它处于 pandas。
- 把时间偏移分开,当作一个
timedelta
to_timedelta
要求格式为 'hh:mm:ss'
所以在 offset 末尾添加 ':00'
- 有关所有可用的时间增量操作,请参阅 Pandas: Time deltas
pandas.Series.dt.tz_convert
pandas.Series.tz_localize
- 通过以下方式转换为特定的 TZ:
- 如果日期时间不是
datetime64[ns, UTC]
dtype,则在 .dt.tz_convert('US/Pacific')
之前先使用 .dt.tz_localize('UTC')
- 否则
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
module provides powerful extensions to the standard 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'], dtype='datetime64[ns, Europe/Berlin]', freq=None)
从网上 API 我收集了一系列数据点,每个数据点都有一个值和一个 ISO 时间戳。不幸的是我需要遍历它们,所以我将它们存储在一个临时的 dict
中,然后从中创建一个 pandas 数据帧并将索引设置为时间戳列(简化示例):
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/non-DST 一切正常,而且,我得到一个带有 DatetimeIndex
的数据框,我以后可以继续工作。
但是,一旦两个不同的时间偏移量出现在一个数据集中(上例),我的数据框中只会得到一个 Index
,它不支持任何基于时间的方法。
有什么方法可以让 pandas 接受时区感知、不同日期作为索引?
我不知道使用时区感知日期时间作为索引并在 pandas 中获取日期时间索引的方法。不过,我确实有一个建议可能会有所帮助,具体取决于您对数据的要求。
将日期时间对象转换为同一时区是否可以接受,或者时区信息是否必须保留?如果您确实需要时区但不一定需要索引,在循环遍历日期时,您可以使用旧时区存储一个新列,或者在新列中复制时区的原始时间,以便仍然可以访问它。
- A pandas
datetime
列也要求偏移量相同。具有不同偏移量的列将不会转换为datetime
dtype。 - 我建议,不要将数据转换为日期时间,直到它处于 pandas。
- 把时间偏移分开,当作一个
timedelta
to_timedelta
要求格式为'hh:mm:ss'
所以在 offset 末尾添加 - 有关所有可用的时间增量操作,请参阅 Pandas: Time deltas
pandas.Series.dt.tz_convert
pandas.Series.tz_localize
- 通过以下方式转换为特定的 TZ:
- 如果日期时间不是
datetime64[ns, UTC]
dtype,则在.dt.tz_convert('US/Pacific')
之前先使用 - 否则
df.datetime_utc.dt.tz_convert('US/Pacific')
.dt.tz_localize('UTC')
- 如果日期时间不是
':00'
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
module provides powerful extensions to the standarddatetime
模块。
问题措辞的小修正(我认为这很重要)。您拥有的是 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'], dtype='datetime64[ns, Europe/Berlin]', freq=None)