【问题标题】:Grouping 1st and last date of a particular week对特定周的第一个和最后一个日期进行分组
【发布时间】:2020-04-19 02:06:03
【问题描述】:

我有一个数据框,其中包含 2015-2019 年的日期。它看起来像这样:

date       | week | value
2016-01-01 | 53   | 3
2016-01-02 | 53   | 7
2016-01-03 | 53   | 1
2016-01-04 | 1    | 9
2016-01-05 | 1    | 4
2016-01-06 | 1    | 8
2016-01-07 | 1    | 4
2016-01-08 | 1    | 5
2016-01-09 | 1    | 6
2016-01-10 | 1    | 20
.
.
.
2016-12-31 | 52   | 31
2017-01-01 | 52   | 2
2017-01-02 | 52   | 49

以上只是数据框的 sn-p,第一列包含 2015-2019 年的每个日期,第二列是日期所属的等周(使用 lubridate)。我正在尝试获取和分组日期,使其仅显示每个等周的第一个日期和最后一个日期,其中一个是:

2016-01-04 | 1    | 9
2016-01-10 | 1    | 20

这很简单,使用 dplyr 的 group_by(年和等周)然后按行号过滤。但是我在这里遇到的问题是,一年的最后几周会溢出到下一年,例如 2016 年的第 52 周。在这种情况下,我无法按年和周分组以获得第一行和最后一行我将在2016年底和2017年初有两组第52周。有没有办法获得每周的第一行和最后一行而无需查看年份。即只过滤每周的第一个条目和最后一个条目,注意这里有多个来自不同年份的第 1 周、第 2 周、第 3 周等等。理想情况下,它应该抛出这样的东西:

date       | week | value
2016-01-01 | 53   | 3
2016-01-03 | 53   | 1
2016-01-04 | 1    | 9
2016-01-10 | 1    | 20
.
.
.
2016-12-31 | 52   | 31
2017-01-02 | 52   | 49
2017-01-03 | 1    | 34
2017-01-09 | 1    | 2

【问题讨论】:

  • 你的意思是如果一周内年份发生变化,你想保留一年的最后一天以及一周的最后一天?
  • 我认为这也是一个问题,所以我实际上决定使用 ISO 年和 ISO 周作为标准化来解决我上面的问题。例如,2017 年的第一周将被定义为 ISO 术语中的第 52 周。

标签: r


【解决方案1】:

一种方法是创建一个新的id 列用于分组

library(data.table)
library(lubridate)
#> 
#> Attaching package: 'lubridate'
#> The following objects are masked from 'package:data.table':
#> 
#>     hour, isoweek, mday, minute, month, quarter, second, wday, week,
#>     yday, year
#> The following objects are masked from 'package:base':
#> 
#>     date, intersect, setdiff, union

dt <- data.table(date = seq(ymd(20160101),ymd(20191231),"days"),value=runif(1461,0,10))


dt[,isoweek:=isoweek(date)]

dt[,id:=paste0(rleid(isoweek),"-",isoweek)]

dt[,.SD[c(1,.N),],by=.(id)]
#>          id       date    value isoweek
#>   1:   1-53 2016-01-01 7.231343      53
#>   2:   1-53 2016-01-03 8.732023      53
#>   3:    2-1 2016-01-04 9.292968       1
#>   4:    2-1 2016-01-10 8.502751       1
#>   5:    3-2 2016-01-11 9.123189       2
#>  ---                                   
#> 416: 208-51 2019-12-22 7.619993      51
#> 417: 209-52 2019-12-23 4.538770      52
#> 418: 209-52 2019-12-29 6.318457      52
#> 419:  210-1 2019-12-30 4.570501       1
#> 420:  210-1 2019-12-31 7.968364       1

dt[,.SD[c(1,.N),],by=.(id)][id=="53-52",]
#>       id       date    value isoweek
#> 1: 53-52 2016-12-26 5.570343      52
#> 2: 53-52 2017-01-01 4.577057      52

reprex package (v0.3.0) 于 2020 年 4 月 19 日创建

【讨论】:

    【解决方案2】:

    我们可以使用lagweek 与之前的值进行比较,并从这个新组中获取第一个和最后一个值。

    library(dplyr)
    
    df %>%
      group_by(grp = cumsum(week != lag(week, default = first(week)))) %>%
      slice(1, n())
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多