2017-02-28 23 views
1

R中,您可以使用cycle()函数轻松返回时间序列对象的cycle部分。例如。你如何将“时期”部分归还到时间序列?

> series <- ts(1:50, frequency = 4, start = 2011) 
> cycle(series) 
    Qtr1 Qtr2 Qtr3 Qtr4 
2011 1 2 3 4 
2012 1 2 3 4 
2013 1 2 3 4 
2014 1 2 3 4 
2015 1 2 3 4 
2016 1 2 3 4 
2017 1 2 3 4 
2018 1 2 3 4 
2019 1 2 3 4 
2020 1 2 3 4 
2021 1 2 3 4 
2022 1 2 3 4 
2023 1 2 

但是,我从来没有能够找出一个干净的方式来回报“期间”部分(如今年的季度数据)。在大多数情况下,你可以做一个简单:

> floor(time(series)) 
    Qtr1 Qtr2 Qtr3 Qtr4 
2011 2011 2011 2011 2011 
2012 2012 2012 2012 2012 
2013 2013 2013 2013 2013 
2014 2014 2014 2014 2014 
2015 2015 2015 2015 2015 
2016 2016 2016 2016 2016 
2017 2017 2017 2017 2017 
2018 2018 2018 2018 2018 
2019 2019 2019 2019 2019 
2020 2020 2020 2020 2020 
2021 2021 2021 2021 2021 
2022 2022 2022 2022 2022 
2023 2023 2023 

为了得到一年,但是,我发现了一些数据(通常是高频率数据),该errors in floating point precision会导致一个周期的第一个时间点返回前一时期的价值(例如,它被存储为2010.9999999而非2011,因此floor()返回2010)。我们可以人为地引入问题转化为数据做如下:

> seriesprec <- ts(1:50, frequency = 4, start = 2010.999999999999) 
> floor(time(seriesprec)) 
    Qtr1 Qtr2 Qtr3 Qtr4 
2011 2010 2011 2011 2011 
2012 2011 2012 2012 2012 
2013 2012 2013 2013 2013 
2014 2013 2014 2014 2014 
2015 2014 2015 2015 2015 
2016 2015 2016 2016 2016 
2017 2016 2017 2017 2017 
2018 2017 2018 2018 2018 
2019 2018 2019 2019 2019 
2020 2019 2020 2020 2020 
2021 2020 2021 2021 2021 
2022 2021 2022 2022 2022 
2023 2022 2023  

现在我们看到的浮点精确度,即使摆脱返回值:

> all.equal(time(seriesprec), time(series)) 
[1] TRUE 

最简单的解决方案,我发现,似乎照顾这些边缘情况是:

round(time(series) - (cycle(series) - 1)*deltat(series)) 

但这似乎是一个非常简单的任务合理复杂的代码。特别是当cycle()是基本函数时,似乎应该有另一个基本函数来返回另一半的时间定义。顺便说一句,我知道处理日期和时间的软件包非常好,但由于我做的很多事情最终都被封装到了软件包中,所以我宁愿不添加诸如lubridate之类的东西作为依赖项可以用一个(非常繁琐的)代码行R来解决。

谢谢!

+0

'TRUNC(时间(ldeaths))' –

+0

@d以获得正确的期间部分。b'time()'为时间序列对象返回的对象不属于'timeDate'类,所以'trunc'四舍五入到特定的时间精度的能力无济于事。相反,它在这个上下文中的功能类似于'floor()',并且具有与该函数相同的浮点精度问题。 – Barker

+0

只需添加少量'floor(时间(系列)+ eps)'您可以使用任何合理的小数字作为'eps'。 'eps < - deltat(series)/ 2'是一般的可能性。 –

回答

1

一种方法可能是在采取floortrunc之前向time添加适当的小数值。由于G.Grothendieck在评论中提到,deltat(series)/2可以是一个合适的小值。并且使用offsettime可以作为添加该小值的一种方式。从?time

偏移

可以用来指示何时采样的时间 单位发生了。 0(默认值)表示单位的开始,0.5中间的 ,1表示时间间隔的结束。

添加offset = 0.5time相当于加入deltat(series)/2

所以,你应该能够使用

floor(time(seriesprec, offset = 0.5)) 
相关问题