日期组件不会计算年份的变化

Date component will not calculate over change in Year

伙计,处理日期很难!!

我有以下数据,正在尝试应用 Tidyverse 原则并对日期组件使用 lubridate

dates <- data.frame(date = as.Date(c('2017-12-17',
                                     '2017-12-28',
                                     '2018-01-03', 
                                     '2018-01-19')))

我想为每个日期定义年份和一年中的星期几,这很简单。

new <- dates %>%
             mutate(c_year = year(date),
                    c_week = week(date))

我真正想知道的是每个 'c_year' 的 'c_week' 开始的确切日期 (ymd)。但是,当我想计算 'c_week' 的开始时,我没有使用 floor_date() 的原始完整日期。所以我在互联网上四处寻找,发现这段代码(大部分)工作正常,可以计算新的 's_create_wk' 变量,顺便说一句,我希望星期一是一周的开始:

new <- dates %>%
             mutate(c_year = year(date),
                    c_week = week(date),
                    s_create_wk = as.Date(paste0(c_year,c_week, "1"),
                                          "%Y%W%u"))

所以理论上我应该得到:

        date   c_year   c_week  start_of_wk 
1 2017-12-17     2017       51   2017-12-11
2 2017-12-28     2017       53   2017-12-25
3 2018-01-03     2018        1   2018-01-01
4 2018-01-19     2018        3   2018-01-15

但我实际得到的是:

        date   c_year   c_week  start_of_wk 
1 2017-12-17     2017       51   2017-12-18
2 2017-12-28     2017       52   2017-12-25
3 2018-01-03     2018        1           NA
4 2018-01-19     2018        3           NA

查看我的 Outlook 日历,2017-12-25 应该在第 53 周,但无论我使用 'week()' 还是 'isoweek()',我都会得到如图所示的实际值。这令人困惑,因为第 51 周对于 2017 年 12 月 17 日的原始日期是正确的。此外,'start_of_wk' 计算 'c_week' 的时间晚了一周 - 这太令人困惑了。如果我减去 7 天,我得到 'c_week' 的正确 'start-of-wk',但这似乎是错误的做法。

长话短说,最大的问题是我在 'start_of_wk' 获得 2018 年日期的 NA,但我不知道为什么!!

抱歉,如果这让我感到困惑,但这肯定让我感到困惑。我猜是日期的格式在计算 's_create_wk' 时出错了,但我尝试了很多组合(Uu、Vv、Ww),或者我使用了错误的包或错误的函数来工作正确日期组件。

感谢您的帮助。

我认为这可以满足您的需求,尽管它需要额外的函数定义才能在管道中工作。 lubridate 有一个设置星期几的 wday 函数,特别是 wday(x) <- 1 会将日期 x 更改为该周的开始日期。参数 week_start 控制哪一天被视为一周的开始;在这里我选择星期一开始一周以适应您想要的输出。

编辑:为了解决关于第 2 行是第 52 周而不是第 53 周的部分,根据我的计算 2017-12-28 是第 52 周,无论您如何计算。例如,week(ymd("2017-12-30")) 是一年中的第 364 天,因此在第 52 周 (52 * 7 = 364),而 week(ymd("2012-12-31")) returns 53 符合预期。

library(tidyverse)
dates <- tibble(date = c('2017-12-17', '2017-12-28', '2018-01-03', '2018-01-19'))

wk_start <- function(date){
  wk_st <- date
  wday(wk_st, week_start = 1) <- 1
  return(wk_st)
}

dates %>%
  mutate(date = ymd(date)) %>%
  mutate(year = year(date),
         week = week(date)
         ) %>%
  mutate(start_of_wk = wk_start(date))
# A tibble: 4 x 4
  date        year  week start_of_wk
  <date>     <dbl> <dbl> <date>     
1 2017-12-17  2017 51.0  2017-12-11 
2 2017-12-28  2017 52.0  2017-12-25 
3 2018-01-03  2018  1.00 2018-01-01 
4 2018-01-19  2018  3.00 2018-01-15 

EDIT2:我四处寻找,我认为您的 as.Date 方法不起作用的原因是数字的间距不正确。查看 paste0(c_year, c_week, "1") 的结果。相反,这种插入垫片的类似方法确实提供了所需的输出,但第一行除外,我仍在考虑:

dates %>%
  mutate(c_year = year(date),
         c_week = week(date),
         s_create_wk = as.Date(str_c(c_year, c_week, "1", sep = "-"), "%Y-%W-%u")
         )
# A tibble: 4 x 4
  date       c_year c_week s_create_wk
  <chr>       <dbl>  <dbl> <date>     
1 2017-12-17   2017  51.0  2017-12-18 
2 2017-12-28   2017  52.0  2017-12-25 
3 2018-01-03   2018   1.00 2018-01-01 
4 2018-01-19   2018   3.00 2018-01-15