按年和周分割日期,并获得每年正确的周数

时间:2017-04-22 12:09:30

标签: r list date data-structures lubridate

使用以下代码,我将日期分为年,将这几年分为几周

library(lubridate)

start = as.Date('2002-01-01')
end = as.Date('2017-01-01')

dates = sample(seq(as.Date('2002-01-01 00:00:00'), as.Date('2017-04-01 00:00:00'), by="day"), end-start,replace = FALSE)

splitByYears = split(dates, year(dates))
splitYearsByWeeks = lapply(splitByYears, function(x) split(x, isoweek(x)))

基于此输出,我做了几次计算。只有当我正在绘制一些数据时,我才注意到这个程序不能完美地运作:

>splitYearsByWeeks
...

$`2011`$`52`
[1] "2011-01-01" "2011-01-02" "2011-12-26"


$`2012`
$`2012`$`1`
[1] "2012-12-31" "2012-01-02" "2012-01-06" "2012-01-08"

...

这里2011-01-01和2011-01-02是2010年第52周的一部分,但由于首先逐年拆分,日期分配到2011年的第52周。同样的问题出现在2012-12-31 ,这个日期是2013年第1周的一部分,但被分配到2012年的第一周,因为我在每年分别申请该功能。

按年分割,而不是每年分成几周给我我需要的格式,但是周年关系不正确。要获得正确的周数,我可以按周划分,按年划分

splitByWeek = split(dates, isoweek(dates))
splitWeeksByYear = lapply(splitByWeek, function(x) split(x, year(x)))

但格式不是我需要的:

>splitWeeksByYear
...
$`53`
$`53`$`2004`
[1] "2004-12-31" "2004-12-29" "2004-12-28"

$`53`$`2005`
[1] "2005-01-01"

$`53`$`2009`
[1] "2009-12-28"

$`53`$`2015`
[1] "2015-12-30"

$`53`$`2016`
[1] "2016-01-03"

以我需要的格式获得正确周的最佳方式是什么:$ year $ weekNum的列表? (也许可以改变第二个结果或以其他方式完成?)

1 个答案:

答案 0 :(得分:0)

根据ISO 8601的周编号有一个好处,即ISO周总是由7天组成,没有重叠或差距(与美国和英国的周编号惯例相反)。

然而,可能会发生新年前后的几天属于与日历日期年度不同的ISO周年的ISO周。

这就是lubridate具有isoyear()isoweek()功能以及format()识别格式说明符%G%g(ISO周)的原因基础年)和%V(ISO周)。

因此,稍微修改一下OP的代码按预期工作:

library(lubridate)
splitByYears = split(dates, isoyear(dates))
splitYearsByWeeks = lapply(splitByYears, function(x) split(x, isoweek(x)))
splitYearsByWeeks$`2011`$`52`
[1] "2011-12-28" "2011-12-27" "2011-12-29" "2011-12-31" "2012-01-01" "2011-12-30"
[7] "2011-12-26"
splitYearsByWeeks$`2012`$`1`
[1] "2012-01-03" "2012-01-07" "2012-01-06" "2012-01-04" "2012-01-08" "2012-01-05"
[7] "2012-01-02"

然而,基于ISO周的年份和ISO周分割dates也可以通过三种略微不同的方式实现:

splitted <- split(dates, format(dates, "%G-W%V"))
splitted$`2011-W52`
[1] "2011-12-28" "2011-12-27" "2011-12-29" "2011-12-31" "2012-01-01" "2011-12-30"
[7] "2011-12-26"
splitted$`2012-W01`
[1] "2012-01-03" "2012-01-07" "2012-01-06" "2012-01-04" "2012-01-08" "2012-01-05"
[7] "2012-01-02"

或者,您可以使用我作为作者的ISOweek package

splitted <- split(dates, ISOweek::ISOweek(dates))

split()函数还接受一系列因子,在这种情况下,他们的交互用于分组:

library(lubridate)
splitted <- split(dates, list(isoyear(dates), isoweek(dates)))
splitted$`2011.52`
[1] "2011-12-28" "2011-12-27" "2011-12-29" "2011-12-31" "2012-01-01" "2011-12-30"
[7] "2011-12-26"
splitted$`2012.1`
[1] "2012-01-03" "2012-01-07" "2012-01-06" "2012-01-04" "2012-01-08" "2012-01-05"
[7] "2012-01-02"