I have a tibble column containing dates, and I want to match them to the nearest higher date in a list of dates. Therefore I wrote a function matchDate
, which I want to call with map
:
library(tidyverse)
d1 = as.Date("2022-01-01")
d2 = as.Date("2022-12-31")
matchDate = function(date,matchDates,...){
matchDates[matchDates >= date] %>% min %>% return
}
df = tibble(date = seq.Date(from=d1,to=d2,by='months'))
dates = seq.Date(from=d2,to=d1,by='-3 months')
df$match = map(df$date,~matchDate(.x,matchDates=dates))
typeof(matchDate(d1,dates))
#> [1] "double"
df
#> # A tibble: 12 x 2
#> date match
#> <date> <list>
#> 1 2022-01-01 <date [1]>
#> 2 2022-02-01 <date [1]>
#> 3 2022-03-01 <date [1]>
#> 4 2022-04-01 <date [1]>
#> 5 2022-05-01 <date [1]>
#> 6 2022-06-01 <date [1]>
#> ...
Created on 2022-05-30 by the reprex package (v2.0.1)
Not sure why typeof
returns double
here, but the function works fine and map
also returns the right dates. The only thing is, it wrappes them into a list (of length one). I tried to add unlist
at different places in my code, but it didn't change anything. Can someone explain what is going on, or how to unlist correctly? Many thanks!
CodePudding user response:
We may flatten it- by default map
returns a list
if we don't specify the suffix for column types i.e. _int
, _dbl
_chr
etc to return a vector
. With Date
class it is a bit complicated as the storage mode is integer/double and this could coerce to its integer storage values
library(purrr)
library(dplyr)
df$match <- map(df$date,~matchDate(.x,matchDates=dates)) %>%
invoke(c,.)
-output
> df
# A tibble: 12 × 2
date match
<date> <date>
1 2022-01-01 2022-03-31
2 2022-02-01 2022-03-31
3 2022-03-01 2022-03-31
4 2022-04-01 2022-07-01
5 2022-05-01 2022-07-01
6 2022-06-01 2022-07-01
7 2022-07-01 2022-07-01
8 2022-08-01 2022-10-01
9 2022-09-01 2022-10-01
10 2022-10-01 2022-10-01
11 2022-11-01 2022-12-31
12 2022-12-01 2022-12-31
With base R
, we can use do.call
with c
do.call("c", map(df$date,~matchDate(.x,matchDates=dates)))
[1] "2022-03-31" "2022-03-31" "2022-03-31" "2022-07-01" "2022-07-01" "2022-07-01" "2022-07-01" "2022-10-01" "2022-10-01" "2022-10-01"
[11] "2022-12-31" "2022-12-31"