How do pipes work with purrr map() function and th

2019-04-29 12:00发布

问题:

When using both pipes and the map() function from purrr, I am confused about how data and variables are passed along. For instance, this code works as I expect:

library(tidyverse)

cars %>% 
  select_if(is.numeric) %>% 
  map(~hist(.))

Yet, when I try something similar using ggplot, it behaves in a strange way.

cars %>% 
  select_if(is.numeric) %>% 
  map(~ggplot(cars, aes(.)) + geom_histogram())

I'm guessing this is because the "." in this case is passing a vector to aes(), which is expecting a column name. Either way, I wish I could pass each numeric column to a ggplot function using pipes and map(). Thanks in advance!

回答1:

cars %>% 
  select_if(is.numeric) %>% 
  map2(., names(.), 
       ~{ggplot(data_frame(var = .x), aes(var)) + 
           geom_histogram() + 
           labs(x = .y)                    })

# Alternate version
cars %>% 
  select_if(is.numeric) %>% 
  imap(.,
       ~{ggplot(data_frame(var = .x), aes(var)) + 
           geom_histogram() + 
           labs(x = .y)                    })

There's a few extra steps.

  • Use map2 instead of map. The first argument is the dataframe you're passing it, and the second argument is a vector of the names of that dataframe, so it knows what to map over. (Alternately, imap(x, ...) is a synonym for map2(x, names(x), ...). It's an "index-map", hence "imap".).
  • You then need to explicitly enframe your data, since ggplot only works on dataframes and coercible objects.
  • This also gives you access to the .y pronoun to name the plots.


回答2:

You aren't supposed to pass raw data to an aesthetic mapping. Instead you should dynamically build the data.frame. For example

cars %>% 
  select_if(is.numeric) %>% 
  map(~ggplot(data_frame(x=.), aes(x)) + geom_histogram())