【问题标题】:Pandas DataFrame Daylight Savings adjustment is wrong during the transition weeks?在过渡周期间,Pandas DataFrame 夏令时调整是否错误?
【发布时间】:2017-08-12 23:02:50
【问题描述】:

我在 CSV 文件中有一个数据集,我将其加载到 Pandas DataFrame 中以按日期+时间进行索引。原始数据是纽约市时间(虽然原始数据中没有体现),我需要从伦敦时间的角度来分析。

在将 EST TimeZone 加载到 DataFrame 之后,我将索引 TimeZone 感知,然后将其转换为 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()

关于如何更好地做到这一点的任何想法?!

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    您需要使用美国/东部作为您的时区。 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(如美国/东部到澳大利亚/等)时,我遇到了 EST 不是的问题t 调整日期,只调整时间;而美国/东部似乎按预期将日期滚动 1。谢谢!
    【解决方案2】:

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

    我确实知道为什么您最后的“快速而肮脏”的手动修复不起作用。 像这样比较 pandas 系列时,不能使用 if、else 或 in。

    这个:

    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 和使用 & |和df.isin

    祝你好运!

    【讨论】:

    • 感谢您的提示。我不知道 'df.isin()' 而是尝试使用我认为仅适用于标量的标准 'in'。但是,这似乎不起作用,因为您建议使用 'df.index.date.isin(shortWnd)' 会引发错误 'AttributeError: 'numpy.ndarray' object has no attribute 'isin'' 而如果我改为试试 'df.index.isin(shortWnd)' 然后它运行没有错误,但不会产生预期的结果——guess 总是返回 False。
    猜你喜欢
    • 1970-01-01
    • 2019-12-02
    • 2018-08-01
    • 2019-11-20
    • 2017-03-02
    • 1970-01-01
    • 2020-11-19
    • 2021-02-17
    • 1970-01-01
    相关资源
    最近更新 更多