Amit Kohli
Amit Kohli

Reputation: 2950

how to pass a character string as a function in purrr map function

So according to the input definition in purrr::map, the .f argument can be:

[...]If character or integer vector, e.g. "y", it is converted to an extractor function, function(x) x[["y"]]. To index deeply into a nested list, use multiple values; c("x", "y") is equivalent to z[["x"]][["y"]]. You can also set .null to set a default to use instead of NULL for absent components.

So it should be possible to pass a VECTOR of characters as the .f call. But I can't figure out how to do that! Clearly if I c('x','y') that won't work because the function assumes I'm drilling down. So how to do it? Some Reprex:


library(purrr)
a <- mtcars %>%
  split(.$cyl) %>% # from base R
  map(~ lm(mpg ~ wt, data = .)) %>%
  map(summary) 

## Works
a %>% map_dbl("r.squared")
#>         4         6         8 
#> 0.5086326 0.4645102 0.4229655

## Also works
a %>%  map_dbl("sigma")
#>        4        6        8 
#> 3.332283 1.165202 2.024091

## But how to get both at once?
a %>%  map("r.squared","sigma")
#> $`4`
#> [1] 0.5086326
#> 
#> $`6`
#> [1] 0.4645102
#> 
#> $`8`
#> [1] 0.4229655
a %>%  map(list("r.squared","sigma"))
#> $`4`
#> NULL
#> 
#> $`6`
#> NULL
#> 
#> $`8`
#> NULL
a %>%  map(c("r.squared","sigma"))
#> $`4`
#> NULL
#> 
#> $`6`
#> NULL
#> 
#> $`8`
#> NULL
a %>%  pmap("r.squared","sigma")
#> $call
#> NULL
#> 
#> $terms
#> NULL
#> 
#> $residuals
#> NULL
#> 
#> $coefficients
#> NULL
#> 
#> $aliased
#> NULL
#> 
#> $sigma
#> NULL
#> 
#> $df
#> NULL
#> 
#> $r.squared
#> NULL
#> 
#> $adj.r.squared
#> NULL
#> 
#> $fstatistic
#> NULL
#> 
#> $cov.unscaled
#> NULL


## There MUST be a more elegant way than:
dplyr::bind_rows(a %>% map_dbl("r.squared"),
          a %>% map_dbl("sigma")) 
#> # A tibble: 2 x 3
#>         `4`       `6`       `8`
#>       <dbl>     <dbl>     <dbl>
#> 1 0.5086326 0.4645102 0.4229655
#> 2 3.3322829 1.1652022 2.0240911

Upvotes: 3

Views: 880

Answers (1)

www
www

Reputation: 39174

If the last tbl in your post is the output you are looking for, you may consider the following approach.

library(purrr)

a <- mtcars %>%
  split(.$cyl) %>% # from base R
  map(~ lm(mpg ~ wt, data = .)) %>%
  map(summary) 

a %>% map_df(~c(.$r.squared, .$sigma))
# A tibble: 2 x 3
        `4`       `6`       `8`
      <dbl>     <dbl>     <dbl>
1 0.5086326 0.4645102 0.4229655
2 3.3322829 1.1652022 2.0240911

Upvotes: 5

Related Questions