3

I think this question is related to Using map_dfr and .id for list names and list of list names but not identical ...

I often use map_dfr for a case where I want to use the value of each argument, not its name, as the .id variable. Here's a silly example: I am computing the mean of mtcars$mpg raised to the second, fourth, and sixth power:

library(tidyverse)
list(2,4,6) %>% map_dfr(~tibble(x=mean(mtcars$mpg^.)), .id="name")
##   name           x
##   <chr>      <dbl>
## 1 1           439.
## 2 2        262350.
## 3 3     198039783.

I would like the name variable to be 2, 4, 6 instead of 1, 2, 3. I can hack this by including setNames(.data) in the pipeline:

list(2,4,6) %>% 
   setNames(.data) %>% 
   map_dfr(~tibble(x=mean(mtcars$mpg^.)), .id="name")

but I wonder if there is a more idiomatic approach I'm missing?


As for the suggestion of using something like ~ tible(name=., ...): nice, but slightly less convenient for the case where the mapping function already returns a tibble, because we have to add an otherwise unnecessary tibble() call:

list(2, 4, 6) %>%   
    map_dfr(~ tibble(name=., 
       broom::tidy(lm(mpg~cyl, data=mtcars, offset=rep(., nrow(mtcars))))))
Ben Bolker
  • 211,554
  • 25
  • 370
  • 453
  • 1
    Why not just `list(2, 4, 6) %>% map_dfr(~ tibble(x = mean(mtcars$mpg^.x), names = .x))`? – tmfmnk Jun 06 '21 at 19:07
  • that works (you can post it as an answer and I will at least upvote) but my example was possibly too simple: there are plenty of cases where the returned object is already a tibble and I don't want to add another `tibble()` statement ... – Ben Bolker Jun 06 '21 at 19:11
  • I'm not sure what exactly is your aim, but for the updated question, you could just do `list(2, 4, 6) %>% map_dfr(~ broom::tidy(lm(mpg~cyl, data=mtcars, offset=rep(., nrow(mtcars)))) %>% mutate(names = .x))`. – tmfmnk Jun 06 '21 at 19:19
  • fair enough. Then the `names` column will be last, though ... (there is [lots of discussion](https://github.com/tidyverse/dplyr/issues/2047) about how/whether we can easily make `mutate` add variables at the beginning/on the left ...) – Ben Bolker Jun 06 '21 at 20:08

3 Answers3

4

OK, I think I found this shortly before posting (so I'll answer). This answer points out that tibble::lst() is a self-naming list function, so as long as we use tibble::lst(2,4,6) instead of list(2,4,6), it Just Works, e.g.

lst(2,4,6) %>% map_dfr(~tibble(x=mean(mtcars$mpg^.)), .id="name")
Ben Bolker
  • 211,554
  • 25
  • 370
  • 453
3

This can work too:

library(tidyverse)

#@ben Bolker answer.
lst(2,4,6) %>% map_dfr(~tibble(x=mean(mtcars$mpg^.)), .id="power")
#> # A tibble: 3 x 2
#>   power          x
#>   <chr>      <dbl>
#> 1 2           439.
#> 2 4        262350.
#> 3 6     198039783.

list(2, 4, 6) %>% map_df(~ tibble(power = as.character(.x) , x = mean(mtcars$mpg^.)))
#> # A tibble: 3 x 2
#>   power          x
#>   <chr>      <dbl>
#> 1 2           439.
#> 2 4        262350.
#> 3 6     198039783.

#another option
seq(2, 6, 2) %>%  map2_df(rerun(length(.), mtcars$mpg), ~ c(x = as.character(.x), mean = round(mean(.y^.x), 0)))
#> # A tibble: 3 x 2
#>   x     mean     
#>   <chr> <chr>    
#> 1 2     439      
#> 2 4     262350   
#> 3 6     198039783

Created on 2021-06-06 by the reprex package (v2.0.0)

jpdugo17
  • 6,816
  • 2
  • 11
  • 23
1

This is also possible, however it would not have been my first choice and only a map would suffice:

library(purrr)

list(2, 4, 6) %>%
  pmap_dfr(~ tibble(power = c(...), x = map_dbl(c(...), ~ mean(mtcars$mpg ^ .x))))

# A tibble: 3 x 2
  power          x
  <dbl>      <dbl>
1     2       439.
2     4    262350.
3     6 198039783.
Anoushiravan R
  • 21,622
  • 3
  • 18
  • 41
  • 1
    works for the simple example I gave (should have included the more complex example up front ...) – Ben Bolker Jun 06 '21 at 20:26
  • Yes it is just possible not at all the best. This would've been my first choice had a similar one would not have been posted earlier: `list(2, 4, 6) %>% map_dfr(~ tibble(name = .x, x = mean(mtcars$mpg^.x)))` . But it would be nice to take a look at a piece of the original data set. – Anoushiravan R Jun 06 '21 at 20:33