Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Post: Passing the dots to a function inside a pipe chain #26

Open
gadenbuie opened this issue Feb 19, 2019 · 0 comments
Open

Post: Passing the dots to a function inside a pipe chain #26

gadenbuie opened this issue Feb 19, 2019 · 0 comments
Assignees

Comments

@gadenbuie
Copy link
Member

gadenbuie commented Feb 19, 2019

Just ran into this problem and made a reprex to figure it out. Wouldn't take much to turn it into a quick blog post about the value of purrr::partial().

library(purrr)
library(tidyr)
library(dplyr)

# NA-ify some populations
population[sample(seq_len(nrow(population)), 100), "population"] <- NA

This is a simple function abstracting a data processing pipe but where we want to pass the ... to a function used inside an anonymous function.

dot_passer <- function(df, ...) {
  df %>% 
    nest(-country) %>% 
    mutate(pop = map_dbl(data, ~ mean(.$population, ...)))
}

This doesn’t work and it gives you a completely bonkers error message. Who said anything about trim?

population %>% 
  dot_passer(na.rm = TRUE)
#> Error in mean.default(.$population, ...): 'trim' must be numeric of length one

But you're convinced this should work because if you put na.rm in the pipe chain directly it works.

population %>% 
  nest(-country) %>% 
  mutate(pop = map_dbl(data, ~ mean(.$population, na.rm = TRUE)))
#> # A tibble: 219 x 3
#>    country             data                    pop
#>    <chr>               <list>                <dbl>
#>  1 Afghanistan         <tibble [19 × 2]> 23703086.
#>  2 Albania             <tibble [19 × 2]>  3235417 
#>  3 Algeria             <tibble [19 × 2]> 34047477.
#>  4 American Samoa      <tibble [19 × 2]>    56705.
#>  5 Andorra             <tibble [19 × 2]>    74590.
#>  6 Angola              <tibble [19 × 2]> 16275446.
#>  7 Anguilla            <tibble [19 × 2]>    12246.
#>  8 Antigua and Barbuda <tibble [19 × 2]>    80887.
#>  9 Argentina           <tibble [19 × 2]> 38252583.
#> 10 Armenia             <tibble [19 × 2]>  3042757.
#> # … with 209 more rows

The ... are not what we think they are inside an anonymous function. If we create a partial function and pass the dots first, outside of the anonymous function, they get where they need to go.

dot_partial_passer <- function(df, ...) {
  p_mean <- partial(mean, ...)
  df %>% 
    nest(-country) %>% 
    mutate(pop = map_dbl(data, ~ p_mean(.$population)))
}

population %>% 
  dot_partial_passer(na.rm = TRUE)
#> # A tibble: 219 x 3
#>    country             data                    pop
#>    <chr>               <list>                <dbl>
#>  1 Afghanistan         <tibble [19 × 2]> 23703086.
#>  2 Albania             <tibble [19 × 2]>  3235417 
#>  3 Algeria             <tibble [19 × 2]> 34047477.
#>  4 American Samoa      <tibble [19 × 2]>    56705.
#>  5 Andorra             <tibble [19 × 2]>    74590.
#>  6 Angola              <tibble [19 × 2]> 16275446.
#>  7 Anguilla            <tibble [19 × 2]>    12246.
#>  8 Antigua and Barbuda <tibble [19 × 2]>    80887.
#>  9 Argentina           <tibble [19 × 2]> 38252583.
#> 10 Armenia             <tibble [19 × 2]>  3042757.
#> # … with 209 more rows

Finally, this might also work because the dots aren’t inside an anonymous function, but it’s a little confusing or could be difficult to set up in more complicated situations.

dot_passer2 <- function(df, ...) {
  df %>% 
    nest(-country) %>% 
    mutate(pop = map(data, "population") %>% map_dbl(mean, ...))
}

population %>% 
  dot_passer2(na.rm = TRUE)
#> # A tibble: 219 x 3
#>    country             data                    pop
#>    <chr>               <list>                <dbl>
#>  1 Afghanistan         <tibble [19 × 2]> 23703086.
#>  2 Albania             <tibble [19 × 2]>  3235417 
#>  3 Algeria             <tibble [19 × 2]> 34047477.
#>  4 American Samoa      <tibble [19 × 2]>    56705.
#>  5 Andorra             <tibble [19 × 2]>    74590.
#>  6 Angola              <tibble [19 × 2]> 16275446.
#>  7 Anguilla            <tibble [19 × 2]>    12246.
#>  8 Antigua and Barbuda <tibble [19 × 2]>    80887.
#>  9 Argentina           <tibble [19 × 2]> 38252583.
#> 10 Armenia             <tibble [19 × 2]>  3042757.
#> # … with 209 more rows
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant