【问题标题】:Start first day of week of the year on Sunday and end last day of week of the year on Saturday从星期日开始一年中一周的第一天,在星期六结束一年中一周的最后一天
【发布时间】:2016-11-29 13:05:03
【问题描述】:

我最近在 R 中遇到了一个处理日期的问题。 2015 年的最后一天 (2015-12-31) 是星期四,这意味着如果我将星期日视为一周的开始日,则一年中的最后一周仅包含 5 天。现在,我希望周五和周六的 2016-01-01 和 2016-01-02 与第 53 周相关联,并从周日的 2016-01-03 开始​​第 1 周。

require(lubridate)
range <- seq(as.Date('2015-12-26'), by = 1, len = 10)
df <- data.frame(range)
df$WKN <- as.numeric(strftime(df$range, format = "%U")) + 1
df$weekday <- weekdays(df$range)
df$weeknum <- wday(df$range)

这会给我以下结果:

df:
range      WKN   weekday   weeknum
2015-12-26  52  Saturday       7
2015-12-27  53    Sunday       1
2015-12-28  53    Monday       2
2015-12-29  53   Tuesday       3
2015-12-30  53 Wednesday       4
2015-12-31  53  Thursday       5
2016-01-01   1    Friday       6
2016-01-02   1  Saturday       7
2016-01-03   2    Sunday       1
2016-01-04   2    Monday       2

现在我想让我的数据框如下:

df:
range      WKN   weekday   weeknum
2015-12-26  52  Saturday       7
2015-12-27  53    Sunday       1
2015-12-28  53    Monday       2
2015-12-29  53   Tuesday       3
2015-12-30  53 Wednesday       4
2015-12-31  53  Thursday       5
2016-01-01  53    Friday       6
2016-01-02  53  Saturday       7
2016-01-03   1    Sunday       1
2016-01-04   1    Monday       2

谁能给我指出一个自动化的方向,这样我就不必每年都更改代码?

【问题讨论】:

    标签: r date datetime dplyr lubridate


    【解决方案1】:

    如果您查看?strptime,则有几个不同的周数令牌可用于format。这里%V 几乎可以工作,除了它从星期一开始一周,所以添加一个来调整:

    df$WKN <- as.integer(format(df$range + 1, '%V'))
    
    df
    ##         range WKN   weekday weeknum
    ## 1  2015-12-26  52  Saturday       7
    ## 2  2015-12-27  53    Sunday       1
    ## 3  2015-12-28  53    Monday       2
    ## 4  2015-12-29  53   Tuesday       3
    ## 5  2015-12-30  53 Wednesday       4
    ## 6  2015-12-31  53  Thursday       5
    ## 7  2016-01-01  53    Friday       6
    ## 8  2016-01-02  53  Saturday       7
    ## 9  2016-01-03   1    Sunday       1
    ## 10 2016-01-04   1    Monday       2
    

    或者,如果您像标签建议的那样使用 dplyr,

    library(dplyr)
    
    df %>% mutate(WKN = as.integer(format(range + 1, '%V')))
    

    返回相同的东西。 lubridate的isoweek函数是等价的,你也可以这样做

    library(lubridate)
    
    df$WKN <- isoweek(df$range + 1)
    

    df %>% mutate(WKN = isoweek(range + 1))
    

    两者都返回与as.integer(format(...)) 版本相同的结果。

    【讨论】:

      【解决方案2】:

      我们可以在逻辑向量上使用cumsum

      df$WKN <- unique(df$WKN)[cumsum(df$weeknum==1) +1]
      df$WKN
      #[1] 52 53 53 53 53 53 53 53  1  1
      

      【讨论】:

        【解决方案3】:

        考虑到您使用的是lubridate,我还想给您一个润滑解决方案。您还要求提供适用于其他年份的解决方案。如下:

        adjust_first_week<- function(year){
        
            first <- floor_date(dmy(paste0("1-1-", year)), "year") 
            two_weeks <- c(first - days(7:1), first + days(0:6))
        
            df <- data.frame(date = two_weeks,
                       day_of_week = weekdays(two_weeks),
                       day_of_year = yday(two_weeks),
                       week_of_year = week(two_weeks))
        
            last_weekend <- which(df$day_of_week == "Sunday")[2] -1
            df$adjust_week <- df$week_of_year
            if(last_weekend ==7) return(df)
            else{
              df$adjust_week[8:last_weekend] <- rep(53,length(8:last_weekend))
            }
            return(df)
          }
        
        1. 采用数字年份,并采用该年的第一天。
        2. 通过在 1/1/year 的任一侧附加一周来创建两周时间段。
        3. 计算当年各种汇总统计数据,供您启迪。
        4. 选择第二个星期天。按照设计,1/1/年始终是第 8 个条目。
        5. 如果星期日是该月的第一天,它不会做任何事情。
        6. 否则,它将覆盖一年中的一周,以便一年中的第一周从第二个星期日开始。

        这是

        的结果
        adjust_last_week(2016)
                 date day_of_week day_of_year week_of_year adjust_week
        1  2015-12-25      Friday         359           52          52
        2  2015-12-26    Saturday         360           52          52
        3  2015-12-27      Sunday         361           52          52
        4  2015-12-28      Monday         362           52          52
        5  2015-12-29     Tuesday         363           52          52
        6  2015-12-30   Wednesday         364           52          52
        7  2015-12-31    Thursday         365           53          53
        8  2016-01-01      Friday           1            1          53
        9  2016-01-02    Saturday           2            1          53
        10 2016-01-03      Sunday           3            1           1
        11 2016-01-04      Monday           4            1           1
        12 2016-01-05     Tuesday           5            1           1
        13 2016-01-06   Wednesday           6            1           1
        14 2016-01-07    Thursday           7            1           1
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-07-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-02-09
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多