How to fix the aspect ratio in ggplot?
In ggplot
the mechanism to preserve the aspect ratio of your plot is to add a coord_fixed()
layer to the plot. This will preserve the aspect ratio of the plot itself, regardless of the shape of the actual bounding box.
(I also suggest you use ggsave
to save your resulting plot to pdf/png/etc, rather than the pdf(); print(p); dev.off()
sequence.)
library(ggplot2)
df <- data.frame(
x = runif(100, 0, 5),
y = runif(100, 0, 5))
ggplot(df, aes(x=x, y=y)) + geom_point() + coord_fixed()
ggplot2: aspect.ratio overpowers coord_equal or coord.fixed
You can force the plot to be square by manually setting the scale of the axes:
gg +
scale_x_continuous(limits=c(min(xy$x,xy$y), max(xy$x,xy$y))) +
scale_y_continuous(limits=c(min(xy$x,xy$y), max(xy$x,xy$y))) +
theme(aspect.ratio=1)
How do I fix an aspect ratio in ggplot2's geom_hex?
One option is to extract the size of the plotting area (in axis units) from the ggplot, then scale the hexagons (using binwidth
rather than bins
argument) based on the ratio.
plt1 = ggplot(iris, aes(x = Sepal.Width, y = Sepal.Length)) +
geom_hex()
xrange = diff(ggplot_build(plt1)$layout$panel_params[[1]]$x.range)
yrange = diff(ggplot_build(plt1)$layout$panel_params[[1]]$y.range)
ratio = xrange/yrange
xbins = 10
xwidth = xrange/xbins
ywidth = xwidth/ratio
plt1 = ggplot(iris, aes(x = Sepal.Width, y = Sepal.Length)) +
geom_hex(binwidth = c(xwidth,ywidth)) +
coord_fixed(ratio = ratio)
ggsave("plot1.pdf", plt1, width = 5, height = 4)
Or, if you prefer the plotting area to have an aspect ratio the same as the page, rather than square, then you can adjust the ratio accordingly:
width = 5
height = 4
ratio = (xrange/yrange) * (height/width)
xwidth = xrange/xbins
ywidth = xwidth/ratio
plt1 = ggplot(iris, aes(x = Sepal.Width, y = Sepal.Length)) +
geom_hex(binwidth = c(xwidth,ywidth)) +
coord_fixed(ratio = ratio)
ggsave("plot1.pdf", plt1, width = width, height = height)
Maintaining Aspect Ratio of Shapes and Images in ggplot/ ggimage
A different approach would be to not use ggimage - e.g., use cowplot for custom annotation, makes it super simple to add an image.
library(ggplot2)
library(cowplot)
p <- ggplot(mpg) +
see::geom_point2(aes(x = displ, y = hwy, size = cty), alpha = 0.2) +
scale_size_identity()
ggdraw(p) +
draw_image("https://upload.wikimedia.org/wikipedia/commons/d/de/Windows_live_square.JPG",
x = .5, y = .3, width = 0.5, height = 0.5)
Created on 2021-02-13 by the reprex package (v1.0.0)
Or, use the ggtextures
package, with a little tweak of the coordinate system
this discussion seems relevant
library(ggtextures)
library(ggplot2)
library(tibble)
img_df <- tibble(
xmin = 1, ymin = 1, xmax = 4, ymax = 4,
image = "https://upload.wikimedia.org/wikipedia/commons/d/de/Windows_live_square.JPG"
)
ggplot(mpg) +
see::geom_point2(aes(x = displ, y = hwy, size = cty), alpha = 0.2) +
geom_textured_rect(data = img_df,
aes(xmin = xmin, xmax = xmax,
ymin = ymin, ymax = ymax, image = image),
nrow = 1,
ncol = 1,
img_width = unit(1, "null"),
img_height = unit(1, "null"),
position = "identity") +
coord_equal() # this is then necessary...
Created on 2021-02-13 by the reprex package (v1.0.0)
How can I adjust the size of two ggplots with a fixed aspect ratio in gridExtra?
EDIT after clarification:
We can use ylim(-150, 200)
in plot1
library(gridExtra)
library(ggplot2)
data(mtcars)
lm1<-lm(disp~drat,data=mtcars)
lm2<-lm(hp~drat,data=mtcars)
lm3<-lm(disp~hp,data=mtcars)
residuals<-data.frame(lm1=residuals(lm1),lm2=residuals(lm2),lm3=residuals(lm3))
(resid2<-grid.arrange(
ggplot(residuals,aes(lm1,lm2))+
geom_point(size=3,shape=21,fill="gray")+
ylim(-150, 200) +
theme_classic()+
ggtitle("Plot1")+
coord_fixed(),
ggplot(residuals,aes(lm1,lm3))+
geom_point(size=3,shape=21,fill="gray")+
ggtitle("Plot2")+
theme_classic()+
coord_fixed(),
nrow=1))
ggplot: keep circle looking round when aspect ratio != 1
You can provide the limits
argument of the position scales as a function that takes the natural limits of the data as the argument. This works with a fixed aspect ratio, but doesn't automatically adapt to fit the available size in the graphics device.
library(tidyverse)
n = 100
radius = 1
circle <- tibble(x = accumulate(1:(n-1), ~ radius*cos(.y*2*pi/n), .init = radius),
y = accumulate(1:(n-1), ~ radius*sin(.y*2*pi/n), .init = 0))
asp <- 3 / 4
ggplot(circle) +
geom_point(aes(x,y), color = "red") +
scale_x_continuous(
limits = function(x) {
mid <- mean(x)
mid + c(-1, 1) * (1/asp) * 0.5 * diff(x)
}
) +
coord_equal()
Created on 2021-07-29 by the reprex package (v1.0.0)
ggplot2: Flip axes and maintain aspect ratio of data
I agree that the theme
solution isn't really a proper one. Here is a solution that does work programatically by calculating the aspect from the actual axes ranges stored in the plot object, but it takes a few lines of code:
ranges <- ggplot_build(p)$layout$panel_ranges[[1]][c('x.range', 'y.range')]
sizes <- sapply(ranges, diff)
aspect <- sizes[1] / sizes[2]
p + coord_flip() + theme(aspect.ratio = aspect)
The solution I would probably use in practice, is to use the horizontal geoms in the ggstance
package (although this may not always be feasible).
Note: This will only give the exact correct answer for two continuous scales with an equal multiplicative extend
argument (i.e. the default).
edit: In many cases I would recommend using coord_equal
combined with the ggstance
package instead of this solution.
Related Topics
How to Subset Data in R Without Losing Na Rows
R: Ggplot2, How to Set the Plot Title to Wrap Around and Shrink the Text to Fit the Plot
Convert Binary String to Binary or Decimal Value
R Shiny Set Datatable Column Width
Way to Securely Give a Password to R Application from the Terminal
Add (Subtract) Months Without Exceeding the Last Day of the New Month
Getting a Stacked Area Plot in R
Add Line Break to Axis Labels and Ticks in Ggplot
How to Group My Date Variable into Month/Year in R
Change Both Legend Titles in a Ggplot with Two Legends
How to Convert Data.Frame to Transactions for Arules
Adding Greek Character to Axis Title
Adding Labels to Ggplot Bar Chart
Generate Markdown Comments Within for Loop
Splitting a File Name into Name,Extension
How to Change Python Path in Reticulate
Why Is Using '<<-' Frowned Upon and How to Avoid It
Find Start and End Positions/Indices of Runs/Consecutive Values