【问题标题】:roll hourly data forward by one year and account for differences in datetimeindex将每小时数据向前滚动一年并考虑 datetimeindex 的差异
【发布时间】:2020-06-10 09:55:02
【问题描述】:

我有很多年的每小时数据,格式如下:

df = pd.DataFrame({'Value': [0, 1, 2, 3, 4]},
     index = [pd.Timestamp('20130101 09:00:00'),
     pd.Timestamp('20130101 10:00:00'),
     pd.Timestamp('20130101 11:00:00'),
     pd.Timestamp('20130101 12:00:00'),
     pd.Timestamp('20130101 13:00:00')])

但是我有从 2013 年到 2019 年底的数据。我想按年向前滚动数据,所以假设我希望从 2013 年滚动到 2014 年的所有值并考虑时间戳差异(所以如果它是闰年,它应该仍然工作)。结果应如下所示:

dfnew = pd.DataFrame({'Value': [0, 1, 2, 3, 4]},
        index = [pd.Timestamp('20140101 09:00:00'),
                pd.Timestamp('20140101 10:00:00'),
                pd.Timestamp('20140101 11:00:00'),
                pd.Timestamp('20140101 12:00:00'),
                pd.Timestamp('20140101 13:00:00')])

编辑:

如果我从 2015 年前滚到 2016 年,那么一年中的小时数会增加 24,因此 29/2 应该向前填充 28/2。 从 2016 年滚动到 2017 年时,它应该按日期(月和日)匹配,并且 29/2 应该再次退出。

编辑 2:

所以我想要这样的东西: df.forwardcopy(yeartobecopied = 2015, pasteedtoyear=2016) 如果粘贴到闰年,则将日、月和小时的值对齐并进行前向填充,如果从闰年复制,则退出 29/2。

编辑 3:

抱歉,这里再次解释了输入和预期输出。从 2015 年滚动到 2016 年。

输入:

    df = pd.DataFrame({'Value': [0, 1, 2, 3]},
     index = [pd.Timestamp('20150228 09:00:00'),
     pd.Timestamp('20150228 10:00:00'),
     pd.Timestamp('20150301 09:00:00'),
     pd.Timestamp('20150301 10:00:00')])

输出:

  df = pd.DataFrame({'Value': [0, 1, 0,1, 2, 3]},
     index = [pd.Timestamp('20160228 09:00:00'),
     pd.Timestamp('20160228 10:00:00'),
     pd.Timestamp('20160229 09:00:00'),
     pd.Timestamp('20160229 10:00:00'),
     pd.Timestamp('20160301 09:00:00'),
     pd.Timestamp('20160301 10:00:00')])

然后从 2016 年到 2017 年。

输入:

  df = pd.DataFrame({'Value': [0, 1, 0,1, 2, 3]},
     index = [pd.Timestamp('20160228 09:00:00'),
     pd.Timestamp('20160228 10:00:00'),
     pd.Timestamp('20160229 09:00:00'),
     pd.Timestamp('20160229 10:00:00'),
     pd.Timestamp('20160301 09:00:00'),
     pd.Timestamp('20160301 10:00:00')])

输出:

 df = pd.DataFrame({'Value': [0, 1, 2, 3]},
     index = [pd.Timestamp('20170228 09:00:00'),
     pd.Timestamp('20170228 10:00:00'),
     pd.Timestamp('20170301 09:00:00'),
     pd.Timestamp('20170301 10:00:00')])

【问题讨论】:

  • 如果2015-02-28 10:00:00 是当前年份,一年后的填充值应该是多少?
  • 是的,如果 2015-02-28 10:00:00 是当前年份,那么 2016-02-28 10:00:00 应该与 2015-02-28 10:00 的值相同:00
  • 你能举出if I roll forward from say 2015 to 2016 then the number of hours in the year increases by 24的例子吗?
  • 是的,这绝对正确。请参阅我的第二次编辑,希望它更清楚

标签: python pandas


【解决方案1】:
In [17]: from dateutil.relativedelta import relativedelta                                                                                                                                                  

In [22]: df.index = [date + relativedelta(years=1) for date in df.index]                                                                                                                                   

In [23]: df                                                                                                                                                                                                
Out[23]: 
                     Value
2014-01-01 09:00:00      0
2014-01-01 10:00:00      1
2014-01-01 11:00:00      2
2014-01-01 12:00:00      3
2014-01-01 13:00:00      4

列表理解是一种解决方法,因为relativedelta 似乎不支持广播。这也应该适用于闰年等。

有趣地尝试pd.Timedelta 有效,但结果错误。

In [10]: df.index + pd.Timedelta('1y')                                                                                                                                                                     
Out[10]: 
DatetimeIndex(['2014-01-01 14:49:12', '2014-01-01 15:49:12',
               '2014-01-01 16:49:12', '2014-01-01 17:49:12',
               '2014-01-01 18:49:12'],
              dtype='datetime64[ns]', freq='H')
In [24]: pd.Timedelta('1y')                                                                                                                                                                                
Out[24]: Timedelta('365 days 05:49:12')

文档也没有提到支持大于天的间隔,但它也没有抛出错误。

【讨论】:

  • 谢谢。但我认为这不会 100% 起作用,因为如果你从非闰年复制你有 8760 小时到有 8784 小时的闰年,我需要以某种方式扩展系列并进行某种填充。没有?
  • 啊,现在我明白你的问题了。是的,你是对的。但是“2016-02-29”应该怎么办?这应该变成“2017-03-01”吗?如果是这样,“2016-12-31”会发生什么?它应该被丢弃吗?填充是一回事,但是闰年之后的几年呢?
  • 它应该按日期匹配,然后应该填充 2016-02-29,当滚动到 2017 时再次下降
  • “2016-02-29”应该填什么? 2015 年没有按日期匹配的值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-01-17
  • 2020-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-23
相关资源
最近更新 更多