My goal is to fix the coordinate aspect ratio of a plot from ggplot2 via coord_fixed()
. I thought coord_fixed(ratio=1)
did the job independently of the scales of the x- or y-axis. My intuition: the argument ratio
refers to the ratio of the total range of coordinate x to the total range of coordinate y. Implying that a ratio of 1 always means that the x-axis will be as long as the y-axis in the plot.
Yet with x-coordinates in the 1000s and y-coordinates e.g. percent, coord_fixed does not behave not as I expect it.
2 Questions:
Here's an illustration
library("ggplot2")
set.seed(123)
df = data.frame(x=runif(11)*1000,y=seq(0,.5,.05))
ggplot(df, aes(x,y)) +geom_point() +coord_fixed(1)
produces
Rescaling the data by the ratio of x- and y-values in coord-fixed solves the issue
ggplot(df, aes(x,y)) +geom_point() +coord_fixed(1*max(df$x)/max(df$y))
However, this is not progammatically. I would have to specify the df$x
manually to achieve the desired effect. See question 2: Is there a sensible way to automatize the re-scaling of the coordinates within coord_fixed
depending on which data is on the x-/y-axis in my ggplot plot?
Can you plain why
coord_fixed
takes the actual scale of the data into account but not the coordinate length as a whole?
That's the point of coord_fixed
. It's especially useful when, e.g., x
and y
are measures of length in the same units. (Basically whenever x
and y
have the same units, coord_fixed
with ratio = 1
is what you want.)
For example, if my data is a square and a triangle, coord_fixed
is the only way to make the square actually square
shapes <- data.frame(x = c(1, 1, 2, 2, 1, 3, 3, 4, 3),
y = c(1, 2, 2, 1, 1, 1, 2, 1, 1),
name = c(rep("square", 5), rep("isosceles triangle", 4)))
shape.plot <- ggplot(shapes, aes(x = x, y = y, group = name, color = name)) +
geom_path()
shape.plot # distorted
shape.plot + coord_fixed() # square!
Can I change the coord_fixed programatically to always refer to the whole range of the x- and y-coordinate values?
I would recommend not overwriting it, you could try to create your own version much as in your answer (though if you want to pull the appropriate values out of the x
and y
specifications of aes()
you'll have a challenge---and you'll learn more about ggplot's internal workings than I know). However, the default behavior (without specifying any coord
) seems to be what you're looking for.
If you compare
# your code
ggplot(df, aes(x,y)) + geom_point() + coord_fixed(1 * max(df$x) / max(df$y))
# no coord at all
ggplot(df, aes(x,y)) + geom_point()
they're basically the same. So, the modification of coord_fixed
you seem to be looking for is don't use coord_fixed
.
coord_fixed
Just found out about this from this semi-related post: if you want a specific aspect ratio of the plot area, you can get it with theme()
,
e.g.
p1 <- ggplot(df, aes(x,y)) + geom_point()
p1 + theme(aspect.ratio = 1)
p1 + theme(aspect.ratio = (1 + sqrt(5))/ 2) # golden ratio portrait
p1 + theme(aspect.ratio = 2 / (1 + sqrt(5))) # golden ratio landscape
This is, of course, data-agnostic. I think the take-home message is that if you want the scales of your data taken into account, relative to each other, use coord_fixed
. If you want to change the aspect ratio of the plotting area but still fit the data, use theme(aspect.ratio)
. If you want to change the aspect ratio of a saved file, use the height and width arguments of your saving function.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With