我创建了一个小时日期数据框,现在我想创建一列来标记每一行(小时)是否处于夏令时。例如,在夏季,标志应== 1,在冬季,标志应==0。
# Localized dates dataframe
dates = pd.DataFrame(data=pd.date_range('2018-1-1', '2019-1-1', freq='h', tz='America/Denver'), columns=['date_time'])
# My failed attempt to create the flag column
dates['dst_flag'] = np.where(dates['date_time'].dt.daylight_saving_time == True, 1, 0)
答案 0 :(得分:1)
评论中有一个不错的链接,至少可以让您手动执行此操作。 AFAIK,没有矢量化的方法可以做到这一点。
import pandas as pd
import numpy as np
from pytz import timezone
# Generate data (as opposed to index)
date_range = pd.to_datetime(pd.date_range('1/1/2018', '1/1/2019', freq='h', tz='America/Denver'))
date_range = [date for date in date_range]
# Localized dates dataframe
df = pd.DataFrame(data=date_range, columns=['date_time'])
# Map transition times to year for some efficiency gain
tz = timezone('America/Denver')
transition_times = tz._utc_transition_times[1:]
transition_times = [t.astimezone(tz) for t in transition_times]
transition_times_by_year = {}
for start_time, stop_time in zip(transition_times[::2], transition_times[1::2]):
year = start_time.year
transition_times_by_year[year] = [start_time, stop_time]
# If the date is in DST, mark true, else false
def mark_dst(dates):
for date in dates:
start_dst, stop_dst = transition_times_by_year[date.year]
yield start_dst <= date <= stop_dst
df['dst_flag'] = [dst_flag for dst_flag in mark_dst(df['date_time'])]
# Do a quick sanity check to make sure we did this correctly for year 2018
dst_start = df[df['dst_flag'] == True]['date_time'][0] # First dst time 2018
dst_end = df[df['dst_flag'] == True]['date_time'][-1] # Last dst time 2018
print(dst_start)
print(dst_end)
此输出:
2018-03-11 07:00:00-06:00
2018-11-04 06:00:00-07:00
这可能是正确的。我没有手动进行UTC转换,也没有进行任何检查以确保小时数在给定的时区正确无误。您至少可以通过快速的Google搜索确认日期是否正确。
pd.date_range
生成 index ,而不是数据。我稍微更改了原始代码,使其成为数据而不是索引。我假设您已经有了数据。
tz._utc_transition_times
的结构有些愚蠢。它是utc DST的开始/停止时间,但是在早期会有一些愚蠢的事情。从1965年开始,情况应该会很好。如果您的日期早于该日期,请将tz._utc_transition_times[1:]
更改为tz._utc_transition_times
。请注意,并非1965年以前都存在。
tz._utc_transition_times
是“ Python专用”。可能会更改而不会发出警告或通知,并且可能会或可能不会对pytz
的将来版本或过去的版本起作用。我正在使用pytz
verion 2017.3。我建议您运行此代码以确保输出匹配,如果不匹配,请确保使用版本2017.3。
HTH,祝您研究/回归问题顺利!
答案 1 :(得分:1)
如果您正在寻找一种矢量化的方式(您应该这样做),则可以使用下面的代码。
这背后的基本思想是找到您所在时区的当前时间与UTC时间之间的时差。在冬季,相差将比UTC多一小时。不管有什么区别,请添加将标志位设置为1或0所需的值。
在丹佛,夏季月份为UTC-6,冬季月份为UTC-7。因此,如果您将丹佛的tz感知时间与UTC时间进行计算,然后加7,则夏季的值为1,冬季的值为0。
import pandas as pd
start = pd.to_datetime('2020-10-30')
end = pd.to_datetime('2020-11-02')
dates = pd.date_range(start=start, end=end, freq='h', tz='America/Denver')
df1 = pd.DataFrame({'dst_flag': 1, 'date1': dates.tz_localize(None)}, index=dates)
# add extra day on each end so that there are no nan's after the join
dates = pd.to_datetime(pd.date_range(start=start - pd.to_timedelta(1, 'd'), end=end + pd.to_timedelta(1, 'd'), freq='h'), utc=True)
df2 = pd.DataFrame({'date2': dates.tz_localize(None)}, index=dates)
out = df1.join(df2)
out['dst_flag'] = (out['date1'] - out['date2']) / pd.to_timedelta(1, unit='h') + 7
out.drop(columns=['date1', 'date2'], inplace=True)
答案 2 :(得分:0)
这是我最终要做的,并且可以满足我的目的:
import pandas as pd
import pytz
# Create dates table and flag Daylight Saving Time dates
dates = pd.DataFrame(data=pd.date_range('2018-1-1', '2018-12-31-23', freq='h'), columns=['date_time'])
# Create a list of start and end dates for DST in each year, in UTC time
dst_changes_utc = pytz.timezone('America/Denver')._utc_transition_times[1:]
# Convert to local times from UTC times and then remove timezone information
dst_changes = [pd.Timestamp(i).tz_localize('UTC').tz_convert('America/Denver').tz_localize(None) for i in dst_changes_utc]
flag_list = []
for index, row in dates['date_time'].iteritems():
# Isolate the start and end dates for DST in each year
dst_dates_in_year = [date for date in dst_changes if date.year == row.year]
spring = dst_dates_in_year[0]
fall = dst_dates_in_year[1]
if (row >= spring) & (row < fall):
flag = 1
else:
flag = 0
flag_list.append(flag)
print(flag_list)
dates['dst_flag'] = flag_list
del(flag_list)
答案 3 :(得分:0)
以下矢量化方法似乎工作正常。 背后的想法与Nick Klavoht的想法相同:找到您所在时区的当前时间与utc时间之间的时差。
# Localized dates dataframe
df = pd.DataFrame(data=pd.date_range('2018-1-1', '2019-1-1', freq='h', tz='America/Denver'), columns=['date_time'])
df['utc_offset'] = df['date_time'].dt.strftime('%z').str[0:3].astype(float)
df['utc_offset_shifted'] = df['utc_offset'].shift(-1)
df['dst'] = df['utc_offset'] - df['utc_offset_shifted']
df_dst = df[(df['dst'] != 0) & (df['dst'])]
df_dst = df_dst.drop(['utc_offset', 'utc_offset_shifted'], axis=1).reset_index(drop=True)
print(df_dst)
这将输出:
date_time dst
0 2018-03-11 01:00:00-07:00 -1.0
1 2018-11-04 01:00:00-06:00 1.0
答案 4 :(得分:0)