我在CSV文件中有一个数据集,我将其加载到Pandas DataFrame中,以按日期+时间进行索引。原始数据是在纽约时间(虽然它没有反映在原始数据中),我需要从伦敦时间的角度对其进行分析。
我将EST TimeZone的索引设置为TimeZone后将其加载到DataFrame中,然后将其转换为Europe / London TimeZone。它似乎运作良好,但不适用于过渡期的日期,在此期间伦敦和纽约之间的时差为4小时,而不是5小时(就像现在,3月下旬)。
CSV文件中的数据如下所示:
2/15/16 10:00 1
2/15/16 10:01 2
3/24/16 10:00 3
3/24/16 10:01 4
3/24/16 10:02 5
3/24/16 10:03 6
3/24/16 11:00 7
3/24/16 11:01 8
以下是简化代码:
import datetime
import pandas as pd
df = pd.read_csv('data/dates.csv', usecols=[0, 1, 2], header=None)
df.columns = ['dt', 'tm', 'val']
df.set_index(pd.DatetimeIndex(df.dt + ' ' + df.tm), inplace=True)
del df['dt']
del df['tm']
print(df)
df.index = df.index.tz_localize('EST', ambiguous='infer').tz_convert('Europe/London')
print(df)
第一个print()
语句的输出如下:
val
2016-02-15 10:00:00 1
2016-02-15 10:01:00 2
2016-03-24 10:00:00 3
2016-03-24 10:01:00 4
2016-03-24 10:02:00 5
2016-03-24 10:03:00 6
2016-03-24 11:00:00 7
2016-03-24 11:01:00 8
第二个print()
的输出如下:
val
2016-02-15 15:00:00+00:00 1
2016-02-15 15:01:00+00:00 2
2016-03-24 15:00:00+00:00 3
2016-03-24 15:01:00+00:00 4
2016-03-24 15:02:00+00:00 5
2016-03-24 15:03:00+00:00 6
2016-03-24 16:00:00+00:00 7
2016-03-24 16:01:00+00:00 8
我的问题是,虽然正常的+ 5小时调整是在2016年2月15日完成的,但在2016年3月24日没有完成,因为该日期属于NYC-的过渡期LDN时差为4小时,而不是5小时。
我已经阅读了很多关于如何正确调整的帖子,并希望ambiguous='infer'
位可能有所帮助,但似乎我仍然做错了?
最后,如果上述难以实现,我不介意做一个手动解决方法。我最终需要做的是根据小时和分钟(从伦敦时间的角度)选择DataFrame的子集到另一个DataFrame中。我现在这样做:
dfSelected = df[(df.index.time >= datetime.time(15, 1))][['val']]
我正在考虑尝试手动和丑陋的东西:
shortWnd = [datetime.date(2016, 3, 24), datetime.date(2016, 3, 23)] # etc....
dfSelected = df[(df.index.time >= datetime.time(15, 1) if (df.index.date in shortWnd) else (df.index.time >= datetime.time(14, 1) ))][['val']]
我根据源DataFrame中的每一行是否在过渡期内手动调整选择窗口,但我收到此错误:
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
关于如何做得更好的任何想法?!
答案 0 :(得分:2)
您需要使用US / Eastern作为您的时区。 EST(东部标准时间)没有考虑DST。
In [47]: pd.Timestamp('20160315').tz_localize('EST')
Out[47]: Timestamp('2016-03-15 00:00:00-0500', tz='EST')
In [48]: pd.Timestamp('20160315').tz_localize('US/Eastern')
Out[48]: Timestamp('2016-03-15 00:00:00-0400', tz='US/Eastern')
In [29]: df = pd.read_csv(StringIO(data), header=None, sep='\s+', parse_dates=[[0, 1]])
In [30]: df.columns = ['date', 'value']
In [31]: df
Out[31]:
date value
0 2016-02-15 10:00:00 1
1 2016-02-15 10:01:00 2
2 2016-03-24 10:00:00 3
3 2016-03-24 10:01:00 4
4 2016-03-24 10:02:00 5
5 2016-03-24 10:03:00 6
6 2016-03-24 11:00:00 7
7 2016-03-24 11:01:00 8
In [32]: df['date_tz'] = df['date'].dt.tz_localize('US/Eastern').dt.tz_convert('Europe/London')
In [33]: df['date_tz2'] = df['date'].dt.tz_localize('EST').dt.tz_convert('Europe/London')
In [34]: df
Out[34]:
date value date_tz date_tz2
0 2016-02-15 10:00:00 1 2016-02-15 15:00:00+00:00 2016-02-15 15:00:00+00:00
1 2016-02-15 10:01:00 2 2016-02-15 15:01:00+00:00 2016-02-15 15:01:00+00:00
2 2016-03-24 10:00:00 3 2016-03-24 14:00:00+00:00 2016-03-24 15:00:00+00:00
3 2016-03-24 10:01:00 4 2016-03-24 14:01:00+00:00 2016-03-24 15:01:00+00:00
4 2016-03-24 10:02:00 5 2016-03-24 14:02:00+00:00 2016-03-24 15:02:00+00:00
5 2016-03-24 10:03:00 6 2016-03-24 14:03:00+00:00 2016-03-24 15:03:00+00:00
6 2016-03-24 11:00:00 7 2016-03-24 15:00:00+00:00 2016-03-24 16:00:00+00:00
7 2016-03-24 11:01:00 8 2016-03-24 15:01:00+00:00 2016-03-24 16:01:00+00:00
答案 1 :(得分:1)
我只能帮助你一点点 - 我不知道时区转换(虽然我怀疑如果你找到合适的选项,它会解决这个问题)
我知道为什么你的'快速和肮脏'手动修复最终不起作用。 在比较像这样的熊猫系列时,你不能使用if,else或者。
这样:
shortWnd = [datetime.date(2016, 3, 24), datetime.date(2016, 3, 23)] # etc....
dfSelected = df[(df.index.time >= datetime.time(15, 1) if (df.index.date in shortWnd) else (df.index.time >= datetime.time(14, 1) ))][['val']]
应该是这样的:
dfSelected = df[((df.index.time >= datetime.time(15, 1) & (df.index.date.isin(shortWnd))) | (df.index.time >= datetime.time(14, 1) ))][['val']]
但我可能误解了你的逻辑。
您需要重写if,else和in using& |和df.isin
祝你好运!