停止地图将日期转换为数字
Stop Map from converting dates to digits
我有一个函数可以找到给定日期的一周的第一天。在这个特定问题中,周确实从星期四开始。
该函数适用于个别日期。
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))
}
}
现在,我想用它作为 dplyr
的管道。所以我修改它以接受带有 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)
}
我认为该函数正在运行,但也对日期应用了一些奇怪的强制转换,因为我最终得到的是数字日期。
> 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
关于如何以正常日期对象结束的任何想法? Map 是否总是在施加强制?
不知道为什么这里要去掉class
属性(使用其他*apply函数时也是如此)。 — 问题在深处似乎是 unlist
下降 classes:
> unlist(list(structure(1, class = 'foo')))
[1] 1
但解决方法非常简单:在末尾设置 class。
此外,我建议不要使用 Map
(returns 和 list
),而是 vapply
。然后我们剩下:
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')
}
您也可以在函数上使用 Vectorize
,但这也会删除 class
属性。
或者,您可以将其保留在 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))
}
我有一个函数可以找到给定日期的一周的第一天。在这个特定问题中,周确实从星期四开始。
该函数适用于个别日期。
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))
}
}
现在,我想用它作为 dplyr
的管道。所以我修改它以接受带有 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)
}
我认为该函数正在运行,但也对日期应用了一些奇怪的强制转换,因为我最终得到的是数字日期。
> 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
关于如何以正常日期对象结束的任何想法? Map 是否总是在施加强制?
不知道为什么这里要去掉class
属性(使用其他*apply函数时也是如此)。 — 问题在深处似乎是 unlist
下降 classes:
> unlist(list(structure(1, class = 'foo')))
[1] 1
但解决方法非常简单:在末尾设置 class。
此外,我建议不要使用 Map
(returns 和 list
),而是 vapply
。然后我们剩下:
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')
}
您也可以在函数上使用 Vectorize
,但这也会删除 class
属性。
或者,您可以将其保留在 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))
}