Maintain ggplot panel size while axis labels change length - r

How can I make the panels of separate ggplots align when the y-axis labels change in length across plots? Below I've saved two subsets of mtcars with longer and shorter model names. Although the overall plots are the same size, the panels are smaller in the mt_long plot because the y-axis labels take up more of the plot.
library(dplyr)
library(ggplot2)
ds_mt <- mtcars %>% rownames_to_column("model")
mt_short <- ds_mt %>% arrange(nchar(model)) %>% slice(1:4)
mt_long <- ds_mt %>% arrange(-nchar(model)) %>% slice(1:4)
plot_short <-
mt_short %>%
ggplot(aes(x = model, y = mpg)) +
geom_col() +
coord_flip()
plot_long <-
mt_long %>%
ggplot(aes(x = model, y = mpg)) +
geom_col() +
coord_flip()
plot_short
plot_long
For this reprex, it is important that the plots be separate. Is there any way to set just the panel dimensions of the plot rather than the overall size of the plot?

We can use gridarrange from the egg package
library(egg)
ggarrange(plot_short, plot_long, ncol = 1)
To save, use
gg <- ggarrange(plot_short, plot_long, ncol = 1)
ggsave("file.png", gg)

try egg::set_panel_size(plot_short)

Related

ggplot2 - Continuous color scale for plot with many lines

I have a data set where I want to plot many lines in a single plot. the lines represent events that are ordered and I would like to use the color scale to represent that order. If I do this, I get
library(purrr)
library(ggplot2)
set.seed(100)
c(1:10) %>% set_names(seq_along(.)) %>%
map(~rnorm(50, 0, 1)) %>% map(cumsum) %>%
imap(~tibble(y=.x, color=as.integer(.y))) %>%
map(mutate, x=row_number()) %>%
reduce(union_all) %>%
ggplot(aes(x=x, y=y, color=color))+ geom_line()
I can solve the issue of the incorrect line by making color a factor
set.seed(100)
c(1:10) %>% set_names(seq_along(.)) %>%
map(~rnorm(50, 0, 1)) %>% map(cumsum) %>%
imap(~tibble(y=.x, color=as.factor(.y))) %>% #this is the only changed line
map(mutate, x=row_number()) %>%
reduce(union_all) %>%
ggplot(aes(x=x, y=y, color=color))+ geom_line()
to get the correct line plot, but now my color scales are discrete and the legend is too. I would like the legend to look like the first example and the plot like the second example. furthermore, in the actual data the events are not uniformly spaced around, so the behavior of the continuous color scale is important because the color conveys distance. I tried group=color but that doesn't work. What aesthetic am I missing here that would help me achieve the desired outcome?
set.seed(100)
c(1:10) %>% set_names(seq_along(.)) %>%
map(~rnorm(50, 0, 1)) %>% map(cumsum) %>%
imap(~tibble(y=.x, color=as.integer(.y))) %>%
map(mutate, x=row_number()) %>%
reduce(union_all) %>%
ggplot(aes(x=x, y=y, group=color, color=color))+ geom_line()

Increasing the size of plot in grid.arrange

I would like to plot a bar chart and a table below it using ggplot2 and knitting to word via Rmd. However, I need my plot to be a bit bigger and my respective table to be a bit smaller. The current code produces a very small bar plot. Below is a working example.
library(tidyverse)
library(grid)
library(gridExtra)
#plot
g <- ggplot(mpg, aes(class))
g<-g + geom_bar()
#table
dat<-mpg %>% count(class) %>%
t() %>%
as.data.frame() %>%
row_to_names(row_number = 1)
table <- tableGrob(dat)
#table and plot
plot2_fin<-grid.arrange(arrangeGrob(nullGrob(), g ,
widths=c(3,8)),
arrangeGrob(arrangeGrob(nullGrob(),table, widths=c(3,18,1)),
heights=c(1,1)))
plot2_fin
You might consider moving from grid to cowplot
library(tidyverse)
library(grid)
library(gridExtra)
#plot
g <- ggplot(mpg, aes(class))
g<-g + geom_bar()
#table
dat<-mpg %>% count(class) %>%
t() %>%
as.data.frame() %>%
row_to_names(row_number = 1)
table <- tableGrob(dat)
#table and plot
library(cowplot)
plot_grid(g, table,
ncol = 1,
rel_heights = c(4, 1))

Define axis dimensions manually in ggplot in R [duplicate]

Is it possible to explicitly set the panel size (i.e., the gray grid panel) in a ggplot? I imagine (but can't find) that there is some ggplot extension that allows for arguments that resemble panel.width = unit(3, "in"), panel.height = unit(4, "in").
I have seen solutions for setting the size of the entire plot, or of getting multiple plots to align using the egg package. But nothing that would let me explicitly set the size of the panel.
library(dplyr)
library(ggplot2)
library(tibble)
ds_mt <- mtcars %>% rownames_to_column("model")
mt_short <- ds_mt %>% arrange(nchar(model)) %>% slice(1:4)
mt_long <- ds_mt %>% arrange(-nchar(model)) %>% slice(1:4)
p_short <-
mt_short %>%
ggplot(aes(x = model, y = mpg)) +
geom_col() +
coord_flip()
p_short
The ggh4x package has a similar function to the egg solution presented in the other answer. A slight convenience is that the plot is still a valid ggplot after using the function, so it would work with ggsave() and other layers can be added afterwards. (disclaimer: I wrote ggh4x)
library(dplyr)
library(ggplot2)
library(tibble)
library(ggh4x)
ds_mt <- mtcars %>% rownames_to_column("model")
mt_short <- ds_mt %>% arrange(nchar(model)) %>% slice(1:4)
mt_long <- ds_mt %>% arrange(-nchar(model)) %>% slice(1:4)
mt_short %>%
ggplot(aes(x = model, y = mpg)) +
geom_col() +
coord_flip() +
force_panelsizes(rows = unit(4, "in"),
cols = unit(3, "in"))
Created on 2021-04-21 by the reprex package (v1.0.0)
You can use set_panel_size() function from the egg package
library(tibble)
library(dplyr)
library(ggplot2)
ds_mt <- mtcars %>% rownames_to_column("model")
mt_short <- ds_mt %>% arrange(nchar(model)) %>% slice(1:4)
mt_long <- ds_mt %>% arrange(-nchar(model)) %>% slice(1:4)
p_short <-
mt_short %>%
ggplot(aes(x = model, y = mpg)) +
geom_col() +
coord_flip()
library(egg)
library(grid)
p_fixed <- set_panel_size(p_short,
width = unit(10, "cm"),
height = unit(4, "in"))
grid.newpage()
grid.draw(p_fixed)
Created on 2018-11-13 by the reprex package (v0.2.1.9000)

How can I append facets and keep individual facet height in the plot as is?

I want to create a large facet_wrap with ggplot2.
What I want is some automatic way to append the individual facets by column so that the facets keep the size they would have by default if (with the same data) only the first row with four columns of facets would be supplied.
E.g. I am concerned about the plot height. I know how to manually change the plot height, but I need an automatic way.
Some example data:
mpg <- mpg %>%
distinct(model, year, .keep_all = TRUE)
ggplot(mpg, aes(x=year, y=hwy))+
geom_point()+
facet_wrap(~model)
All facets should have the same height as
mpg %>%
distinct(model, year, .keep_all = TRUE) %>%
filter(model %in% c("4runner 4wd", "a4", "a4 quattro", "altima")) %>%
ggplot(aes(x=year, y=hwy))+
geom_point()+
facet_wrap(~model, ncol = 4)
You can conserve plot height by using theme(aspect.ratio). For example,
mpg <- mpg %>%
distinct(model, year, .keep_all = TRUE)
ggplot(mpg, aes(x=year, y=hwy))+
geom_point()+
facet_wrap(~model) + theme(aspect.ratio=2)

ggplot: position_dodge results in overlap?

I have the following workflow:
rm(list=ls())
data(mtcars)
attach(mtcars)
library(ggplot2)
library(plyr)
library(dplyr)
library(scales)
library(reshape2)
library(lazyeval)
my_func <- function(x, y) {
test<<-mtcars %>% group_by_(x, y) %>%
summarise(Freq = n()) %>%
mutate(Freq = Freq/sum(Freq))
test
}
my_func('gear', 'cyl')
ggplot(test, aes(x=gear, y=Freq))+
geom_bar(stat="identity", aes(fill=cyl), position=position_dodge(width=0.1))+
scale_y_continuous(labels=percent_format(), limits = c(0,1))
However, the resulting plot does not show the bars next to one another, but rather some on top of one another. What gives and how do I fix this?
You need to convert the cyl column to factor.
test$cyl <- as.factor(test$cyl)
ggplot(test, aes(x=gear, y=Freq))+
geom_bar(stat="identity", aes(fill=cyl), position=position_dodge(width=1))+
scale_y_continuous(labels=percent_format(), limits = c(0,1))

Resources