7
votes

Is there a way to map to any type with purrr::map

library(tidyverse)
library(lubridate)

df <- data_frame(id = c(1, 1, 1, 2, 2, 2), 
                 val = c(1, 2, 3, 1, 2, 3), 
                 date = ymd("2017-01-01") + days(1:6))

df1 <- df %>% nest(-id) %>% 
  mutate(first_val = map_dbl(data, ~ .$val[1]), 
         first_day = map(data, ~ .$date[1]))

I would like first_day to be a column of type <date> as in df. I have tried flatten, but this does not work as it coerces the column to numeric.

2

2 Answers

10
votes

purrr is type-stable and this takes some getting used to.

In this case, it returns a list where you expect a <date>.

A simple and "stable" solution to you case would be to replace the second map with a map_dbl and have the output turned back to a <date> object using lubridate's as_date, like this:

df3 <- df %>% nest(-id) %>% 
   mutate(first_val = map_dbl(data, ~ .$val[1]), 
          first_day = as_date(map_dbl(data, ~ .$date[1])))

You get:

# A tibble: 2 × 4
  id             data                 first_val  first_day
 <dbl>          <list>                  <dbl>     <date>
 1              <tibble [3 × 2]>         1      2017-01-02
 2              <tibble [3 × 2]>         1      2017-01-05

Which is what you wanted (for this example).

EDIT: for any other types (other than <date>) you would have to find a different solution, however, the standard types are covered by the dedicated map_lgl, map_dbl, map_chr, etc.

5
votes

An alternative to the map_dbl() %>% as_date() is to use unnest() on the output column of interest:

library(tidyverse)
library(lubridate)
#> 
#> Attaching package: 'lubridate'
#> The following object is masked from 'package:base':
#> 
#>     date

df <- data_frame(id = c(1, 1, 1, 2, 2, 2), 
                 val = c(1, 2, 3, 1, 2, 3), 
                 date = ymd("2017-01-01") + days(1:6))

df %>% nest(-id) %>% 
  mutate(first_val = map_dbl(data, ~ .$val[1]), 
         first_day = map(data, ~ .$date[1])) %>% 
  unnest(first_day)
#> # A tibble: 2 x 4
#>      id data             first_val first_day 
#>   <dbl> <list>               <dbl> <date>    
#> 1     1 <tibble [3 × 2]>         1 2017-01-02
#> 2     2 <tibble [3 × 2]>         1 2017-01-05

Created on 2018-11-17 by the reprex package (v0.2.1)