Home > Enterprise >  Map returns lists instead of dates
Map returns lists instead of dates

Time:05-31

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"
  • Related