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!
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 ofmap
. The first argument is the dataframe you're passing it, and the second argument is a vector of thenames
of that dataframe, so it knows what tomap
over. (Alternately,imap(x, ...)
is a synonym formap2(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.
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())
来源:https://stackoverflow.com/questions/45362462/how-do-pipes-work-with-purrr-map-function-and-the-dot-symbol