简体   繁体   中英

Can I set free scales for aesthetics other than x and y (e.g. size) when using facet_grid?

facet_grid and facet_wrap have the scales parameter, which as far as I know allows each plot to adjust the scales of the x and/or y axis to the data being plotted. Since according to the grammar of ggplot x and y are just two among many aesthetics, and there's a scale for each aesthetic, I figured it would be reasonable to have the option of letting each aesthetic be free, but so far I didn't find a way to do it.

I was trying to set it in particular for the Size, since sometimes a variables lives in a different order of magnitude depending on the group I'm using for the facet, and having the same scale for every group blocks the possibility of seeing within-group variation.

A reproducible example:

set.seed(1)
x <- runif(20,0,1)
y <- runif(20,0,1)
groups <- c(rep('small', 10), rep('big', 10))
size_small <- runif(10,0,1)
size_big   <- runif(10,0,1) * 1000

df <- data.frame(x, y, groups, sizes = c(size_small, size_big))

And an auxiliary function for plotting:

basic_plot <- function(df) ggplot(df) + 
  geom_point(aes(x, y, size = sizes, color = groups)) + 
  scale_color_manual(values = c('big' = 'red', 'small' = 'blue')) +
  coord_cartesian(xlim=c(0,1), ylim=c(0,1))

If I we plot the data as is, we get the following:

basic_plot(df)

Non faceted plot

The blue dots are relatively small, but there is nothing we can do. If we add the facet:

basic_plot(df) +
  facet_grid(~groups, scales = 'free')

Faceted plot

The blue dots continue being small. But I would like to take advantage of the fact that I'm dividing the data in two, and allow the size scale to adjust to the data of each plot. I would like to have something like the following:

plot_big <- basic_plot(df[df$groups == 'big',])
plot_small <- basic_plot(df[df$groups == 'small',])

grid.arrange(plot_big, plot_small, ncol = 2)

What I want

Can it be done without resorting to this kind of micromanaging, or a manual rescaling of the sizes like the following?

df %>% 
  group_by(groups) %>% 
  mutate(maximo = max(sizes),
         sizes = scale(sizes, center = F)) %>% 
  basic_plot() +
  facet_grid(~groups)

I can manage to do those things, I'm just trying to see if I'm not missing another option, or if I'm misunderstanding the grammar of graphics.

Thank you for your time!

As mentioned, original plot aesthetics are maintained when calling facet_wrap . Since you need grouped graphs, consider base::by (the subsetting data frame function) wrapped in do.call :

do.call(grid.arrange, 
        args=list(grobs=by(df, df$groups, basic_plot), 
                  ncol=2,
                  top="Grouped Point Plots"))

分组绘图输出


Should you need to share a legend, I always use this wrapper from @Steven Lockton's answer

do.call(grid_arrange_shared_legend, by(df, df$groups, basic_plot))

共享图例绘图输出

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM