简体   繁体   English

阻止地图将日期转换为数字

[英]Stop Map from converting dates to digits

I have a function that find the first day of the week for a given date. 我有一个功能,可以找到给定日期的一周的第一天。 In this particular problem, weeks do start on Thursday. 在这个特殊的问题上,星期几从星期四开始。

The function works well for individual dates. 该功能适用​​于各个日期。

week_commencing <- function(date) {
  weekday <- lubridate::wday(date)
  if (weekday >= 5) { 
    return(date - lubridate::days(weekday) + lubridate::days(5))
  } else {
    return(date - lubridate::days(weekday) - lubridate::days(2))
  } 
}

Now, I would like to use it a pipe with dplyr . 现在,我想将它与dplyr一起使用。 So I modified it to accept columns with Map . 所以我修改了它以接受Map列。

week_commencing <- function(dates) {
  Map(function(date) {
    weekday <- lubridate::wday(date)
    if (weekday >= 5) { 
      return(date - lubridate::days(weekday) + lubridate::days(5))
    } else {
      return(date - lubridate::days(weekday) - lubridate::days(2))
    } 
  },dates)
}

I think the function is working, but is also applying some weird coercion to the dates because I end up with digit dates. 我认为该功能有效,但同时对日期应用了一些奇怪的强制,因为我最终使用数字日期。

> test <- data.frame(datetime=seq.Date(as.Date("2016-06-01"),as.Date("2016-06-10"), by='day'))
> test
     datetime
1  2016-06-01
2  2016-06-02
3  2016-06-03
4  2016-06-04
5  2016-06-05
6  2016-06-06
7  2016-06-07
8  2016-06-08
9  2016-06-09
10 2016-06-10

> test %>% mutate(datetime=week_commencing(datetime))
   datetime
1     16947
2     16954
3     16954
4     16954
5     16954
6     16954
7     16954
8     16954
9     16961
10    16961

Any ideas on how to end up with normal date object? 关于如何以正常日期对象结束的任何想法? Is Map always applying coercion? 地图是否总是施加强制性?

I don't know why the class attribute is dropped here (the same happens when using other *apply functions). 我不知道为什么将class属性放在这里(使用其他* apply函数时也会发生同样的情况)。 — The issue, deep down, seems to be that unlist drops classes: —从unlist ,问题似乎在于unlist删除类:

> unlist(list(structure(1, class = 'foo')))
[1] 1

But the fix is straightforward enough: set the class at the end. 但是解决方法很简单:将类放在最后。

Furthermore, I'd suggest not using Map (which returns a list ) but rather vapply . 此外,我建议不要使用Map (它返回一个list ),而是使用vapply Then we're left with: 然后我们剩下:

week_commencing <- function(dates) {
  wc <- function(date) {
    weekday <- lubridate::wday(date)
    if (weekday >= 5) { 
      return(date - lubridate::days(weekday) + lubridate::days(5))
    } else {
      return(date - lubridate::days(weekday) - lubridate::days(2))
    } 
  }

  structure(vapply(dates, wc, numeric(1)), class = 'Date')
}

You could also use Vectorize on the function, but that also removes the class attribute. 您也可以在该函数上使用Vectorize ,但这也会删除class属性。

Or, you could keep it in the dplyr family: 或者,您可以将其保留在dplyr系列中:

week_commencing <- function(date) {
  weekday <- lubridate::wday(date)
  dplyr::if_else(weekday >= 5,
                 date - lubridate::days(weekday) + lubridate::days(5),
                 date - lubridate::days(weekday) - lubridate::days(2))
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM