## How to specify the size of a graph in ggplot2 independent of axis labels

Use `ggplotGrob`

. Something like this:

`g1 <- ggplot(...)`

g2 <- ggplot(...)

g1grob <- ggplotGrob(g1)

g2grob <- ggplotGrob(g2)

grid.arrange(g1grob, g2grob)

## How to maintain size of ggplot with long labels

There a several ways to avoid overplotting of labels or squeezing the plot area or to improve readability in general. Which of the proposed solutions is most suitable will depend on the lengths of the labels and the number of bars, and a number of other factors. So, you will probably have to play around.

#### Dummy data

Unfortunately, the OP hasn't included a reproducible example, so we we have to make up our own data:

`V1 <- c("Long label", "Longer label", "An even longer label",`

"A very, very long label", "An extremely long label",

"Long, longer, longest label of all possible labels",

"Another label", "Short", "Not so short label")

df <- data.frame(V1, V2 = nchar(V1))

yaxis_label <- "A rather long axis label of character counts"

#### "Standard" bar chart

Labels on the x-axis are printed upright, overplotting each other:

`library(ggplot2) # version 2.2.0+`

p <- ggplot(df, aes(V1, V2)) + geom_col() + xlab(NULL) +

ylab(yaxis_label)

p

Note that the recently added `geom_col()`

instead of `geom_bar(stat="identity")`

is being used.

#### OP's approach: rotate labels

Labels on x-axis are rotated by 90° degrees, squeezing the plot area:

`p + theme(axis.text.x = element_text(angle = 90))`

#### Horizontal bar chart

All labels (including the y-axis label) are printed upright, improving readability but still squeezing the plot area (but to a lesser extent as the chart is in landscape format):

`p + coord_flip()`

#### Vertical bar chart with labels wrapped

Labels are printed upright, avoiding overplotting, squeezing of plot area is reduced. You may have to play around with the `width`

parameter to `stringr::str_wrap`

.

`q <- p + aes(stringr::str_wrap(V1, 15), V2) + xlab(NULL) +`

ylab(yaxis_label)

q

#### Horizontal bar chart with labels wrapped

My favorite approach: All labels are printed upright, improving readability,

squeezing of plot area are is reduced. Again, you may have to play around with the `width`

parameter to `stringr::str_wrap`

to control the number of lines the labels are split into.

`q + coord_flip()`

#### Addendum: Abbreviate labels using `scale_x_discrete()`

For the sake of completeness, it should be mentioned that `ggplot2`

is able to abbreviate labels. In this case, I find the result disappointing.

`p + scale_x_discrete(labels = abbreviate)`

## How to arrange `ggplot2` objects side-by-side and ensure equal plotting areas?

One suggestion: the `patchwork`

package.

`library(patchwork)`

plot_a + plot_b

It also works for more complex layouts, e.g.:

`(plot_a | plot_b) / plot_a`

## How can I make consistent-width plots in ggplot (with legends)?

**Edit:** Very easy with `egg`

package

`# install.packages("egg")`

library(egg)

p1 <- ggplot(data.frame(x=c("a","b","c"),

y=c("happy","sad","ambivalent about life")),

aes(x=factor(0),fill=x)) +

geom_bar()

p2 <- ggplot(data.frame(x=c("a","b","c"),

y=c("happy","sad","ambivalent about life")),

aes(x=factor(0),fill=y)) +

geom_bar()

ggarrange(p1,p2, ncol = 1)

**Original** Udated to ggplot2 2.2.1

Here's a solution that uses functions from the `gtable`

package, and focuses on the widths of the legend boxes. (A more general solution can be found here.)

`library(ggplot2) `

library(gtable)

library(grid)

library(gridExtra)

# Your plots

p1 <- ggplot(data.frame(x=c("a","b","c"),y=c("happy","sad","ambivalent about life")),aes(x=factor(0),fill=x)) + geom_bar()

p2 <- ggplot(data.frame(x=c("a","b","c"),y=c("happy","sad","ambivalent about life")),aes(x=factor(0),fill=y)) + geom_bar()

# Get the gtables

gA <- ggplotGrob(p1)

gB <- ggplotGrob(p2)

# Set the widths

gA$widths <- gB$widths

# Arrange the two charts.

# The legend boxes are centered

grid.newpage()

grid.arrange(gA, gB, nrow = 2)

If in addition, the legend boxes need to be left justified, and borrowing some code from here written by @Julius

`p1 <- ggplot(data.frame(x=c("a","b","c"),y=c("happy","sad","ambivalent about life")),aes(x=factor(0),fill=x)) + geom_bar()`

p2 <- ggplot(data.frame(x=c("a","b","c"),y=c("happy","sad","ambivalent about life")),aes(x=factor(0),fill=y)) + geom_bar()

# Get the widths

gA <- ggplotGrob(p1)

gB <- ggplotGrob(p2)

# The parts that differs in width

leg1 <- convertX(sum(with(gA$grobs[[15]], grobs[[1]]$widths)), "mm")

leg2 <- convertX(sum(with(gB$grobs[[15]], grobs[[1]]$widths)), "mm")

# Set the widths

gA$widths <- gB$widths

# Add an empty column of "abs(diff(widths)) mm" width on the right of

# legend box for gA (the smaller legend box)

gA$grobs[[15]] <- gtable_add_cols(gA$grobs[[15]], unit(abs(diff(c(leg1, leg2))), "mm"))

# Arrange the two charts

grid.newpage()

grid.arrange(gA, gB, nrow = 2)

**Alternative solutions** There are `rbind`

and `cbind`

functions in the `gtable`

package for combining grobs into one grob. For the charts here, the widths should be set using `size = "max"`

, but the CRAN version of `gtable`

throws an error.

One option: It should be obvious that the legend in the second plot is wider. Therefore, use the `size = "last"`

option.

`# Get the grobs`

gA <- ggplotGrob(p1)

gB <- ggplotGrob(p2)

# Combine the plots

g = rbind(gA, gB, size = "last")

# Draw it

grid.newpage()

grid.draw(g)

Left-aligned legends:

`# Get the grobs`

gA <- ggplotGrob(p1)

gB <- ggplotGrob(p2)

# The parts that differs in width

leg1 <- convertX(sum(with(gA$grobs[[15]], grobs[[1]]$widths)), "mm")

leg2 <- convertX(sum(with(gB$grobs[[15]], grobs[[1]]$widths)), "mm")

# Add an empty column of "abs(diff(widths)) mm" width on the right of

# legend box for gA (the smaller legend box)

gA$grobs[[15]] <- gtable_add_cols(gA$grobs[[15]], unit(abs(diff(c(leg1, leg2))), "mm"))

# Combine the plots

g = rbind(gA, gB, size = "last")

# Draw it

grid.newpage()

grid.draw(g)

A second option is to use `rbind`

from Baptiste's `gridExtra`

package

`# Get the grobs`

gA <- ggplotGrob(p1)

gB <- ggplotGrob(p2)

# Combine the plots

g = gridExtra::rbind.gtable(gA, gB, size = "max")

# Draw it

grid.newpage()

grid.draw(g)

Left-aligned legends:

`# Get the grobs`

gA <- ggplotGrob(p1)

gB <- ggplotGrob(p2)

# The parts that differs in width

leg1 <- convertX(sum(with(gA$grobs[[15]], grobs[[1]]$widths)), "mm")

leg2 <- convertX(sum(with(gB$grobs[[15]], grobs[[1]]$widths)), "mm")

# Add an empty column of "abs(diff(widths)) mm" width on the right of

# legend box for gA (the smaller legend box)

gA$grobs[[15]] <- gtable_add_cols(gA$grobs[[15]], unit(abs(diff(c(leg1, leg2))), "mm"))

# Combine the plots

g = gridExtra::rbind.gtable(gA, gB, size = "max")

# Draw it

grid.newpage()

grid.draw(g)

## Change axes label and scale using ggplot and patchwork in R

You could add two additional arguments to your function, one for the axis label and one for your desired limits.

`library(ggplot2)`

library(patchwork)

d <- cars

d$Obs <- c(1:50)

f1 <- function(a, y_lab) {

ggplot(data = d, aes_string(x = "Obs", y = a)) +

geom_line() +

scale_y_continuous(limits = range(c(d$speed, d$dist))) +

labs(x = "Observation", y = y_lab)

}

f1("speed", "Speed") + f1("dist", "Distance")

## ggplot with 2 y axes on each side and different scales

Sometimes a client wants two y scales. Giving them the "flawed" speech is often pointless. But I do like the ggplot2 insistence on doing things the right way. I am sure that ggplot is in fact educating the average user about proper visualization techniques.

Maybe you can use faceting and scale free to compare the two data series? - e.g. look here: https://github.com/hadley/ggplot2/wiki/Align-two-plots-on-a-page

## allign dimensions of separat plots

Inside cowplot, there is a function `align_margin`

that aligns your left and right margins in a list of ggplot grobs.

We include a few more plots:

`p1 <- ggplot(iris, aes(Sepal.Length, Species)) + `

geom_density_ridges()

p2 <- ggplot(mtcars) +

geom_point(aes(mpg, disp))

p3 <- ggplot(PlantGrowth) +

geom_boxplot(aes(group, weight))

p4 <- ggplot(USArrests) +

geom_point(aes(Assault, UrbanPop))

With some slight modification from the vignette:

`grobs <- lapply(list(p1, p2, p3,p4), as_grob)`

plot_widths <- lapply(grobs, function(x) {x$widths})

aligned_widths <- align_margin(align_margin(plot_widths, "first"),"last")

# reset widths

for (i in seq_along(plots)) {

grobs[[i]]$widths <- aligned_widths[[i]]

}

To get all in a page:

`plot_grid(plotlist = grobs, ncol = 1)`

To get individual:

`grid.draw(grobs[[1]])`

### Related Topics

How to Get Rowsums for Selected Columns in R

Remove Space Between Plotted Data and the Axes

Remove Unwanted Symbols from Expression Function - R

Add Row to a Data Frame With Total Sum for Each Column

Count Number of Rows Within Each Group

How to Create a Lag Variable Within Each Group

How to Convert Excel Date Format to Proper Date in R

Create a Sequential Number (Counter) For Rows Within Each Group of a Dataframe

Create Counter With Multiple Variables

R Collapse Multiple Rows into 1 Row - Same Columns

How to Dplyr Rename a Column, by Column Index

Conditional Replacement of a Comma With a Dot in a Numeric Column

How to Generate a Histogram for Each Column of My Table

Extract Row Corresponding to Minimum Value of a Variable by Group

Why Are My Dplyr Group_By & Summarize Not Working Properly? (Name-Collision With Plyr)