Python 熊猫数据框夏令时调整在过渡周内出错?

Python 熊猫数据框夏令时调整在过渡周内出错?,python,pandas,dataframe,Python,Pandas,Dataframe,我在CSV文件中有一个数据集,我正在将其加载到熊猫数据框中,以按日期+时间索引。原始数据是纽约市时间,虽然它没有反映在原始数据中,我需要从伦敦时间的角度进行分析 在将索引时区加载到数据帧中之后,我将其识别为EST时区,然后将其转换为欧洲/伦敦时区。这似乎效果不错,但对于进入过渡期的日期来说并非如此,在过渡期内,伦敦和纽约之间的时差为4小时,而不是像现在3月底那样的5小时 CSV文件中的数据如下所示: 2/15/16 10:00 1 2/15/16 10:01 2 3/24/16 10:0

我在CSV文件中有一个数据集,我正在将其加载到熊猫数据框中,以按日期+时间索引。原始数据是纽约市时间,虽然它没有反映在原始数据中,我需要从伦敦时间的角度进行分析

在将索引时区加载到数据帧中之后,我将其识别为EST时区,然后将其转换为欧洲/伦敦时区。这似乎效果不错,但对于进入过渡期的日期来说并非如此,在过渡期内,伦敦和纽约之间的时差为4小时,而不是像现在3月底那样的5小时

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
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']]
以下是简化代码:

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
                         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
第二次打印的输出如下:

                    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
                         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日不正确,因为该日期属于过渡期,纽约市LDN时差为4小时,而不是5小时

我已经阅读了很多关于如何正确调整的帖子,希望模棱两可的class='infer'可能会有所帮助,但似乎我仍然在做错事

最后,如果上述内容很难实现,我不介意手动解决。我最终需要做的是根据伦敦时间的小时和分钟,将数据帧的子集选择到另一个数据帧中。我现在是这样做的:

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
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']]
我想尝试一些像这样的手工和丑陋的东西:

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
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']]
根据源数据帧中的每一行是否在过渡期内,我手动调整选择窗口,但我得到以下错误:

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

有什么办法可以做得更好吗

我只能帮你一点忙-我不知道时区转换,尽管我怀疑如果你在那里找到正确的选项,它会解决这个问题

但我知道为什么你最后的“快速而肮脏”的手动修复不起作用。 在比较熊猫系列时,不能使用if、else或in

这:

应该是这样的:

dfSelected = df[((df.index.time >= datetime.time(15, 1) & (df.index.date.isin(shortWnd))) | (df.index.time >= datetime.time(14, 1)  ))][['val']]
但我可能误解了你的逻辑

您需要重写if、else和使用&| and


祝你好运

您的时区需要使用美国/东部。东部标准时间不考虑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

谢谢你的提示。我不知道'df.isin'而是试图使用标准'in',我想它只适用于标量。但是,这似乎不起作用,因为使用您建议的“df.index.date.isinshortWnd”会抛出一个错误“AttributeError:“numpy.ndarray”对象没有属性“isin”,如果我改为只使用“df.index.isinshortWnd”,那么它将运行而不会出错,但是,这并不能产生期望的结果-猜测总是返回False。你说得对,谢谢!这似乎也解决了我一直在努力解决的另一个问题——时区转换何时也应该将日期调整为+1,就像在美国/从东部到澳大利亚/等等。我遇到了一个问题,EST没有调整日期,只是调整时间;而美国/东方航空似乎按预期将日期推迟了1天。谢谢