5

I am plotting a fairly simple scatterplot using ggplot. I am mainly interested in illustrating a correlation between the x and y axis. Therefore, I would like the limits of the xaxis to equal that of the yaxis.

ggplot(VV,aes(x=R1_Zsc,y=R2_Zsc)) +
  geom_point() +
  stat_smooth() +
  facet_wrap(~variable, scales="free")

I tried the variants below but that didn't work either:

ggplot(VV, aes(x=R1_Zsc,y=R2_Zsc)) +
  geom_point() +
  stat_smooth() +
  xlim=range(c(VV$R1_Zsc,VV$R2_Zsc)) +
  ylim=range(c(VV$R1_Zsc,VV$R2_Zsc)) +
  facet_wrap(~variable, scales="free")

I have made a data frame containingt he xlimits and y limits for each variable, and thought I could use this, but I'm not sure how.

df_rng <- ddply(VV, .(variable), summarise, min=range(c(R1_Zsc,R2_Zsc))[1],max=range(c(R1_Zsc,R2_Zsc))[2])

Any help is appreciated.

Thanks, coord_fixed(ratio=1) does not seem to work. I want to set the xlim and ylim to the same values.

Here is the output plot enter image description here

The example from the cars dataset produces the following graph:

enter image description here

Jaap
  • 81,064
  • 34
  • 182
  • 193
user2814482
  • 631
  • 1
  • 10
  • 28
  • I can't add an answer, but a very simple solution is to add invisible data to the plot with x and y reversed so that the plotted points are always square, e.g., `+ geom_blank(aes(x=R2_Zsc,y=R1_Zsc))` – Simon Woodward Nov 23 '18 at 20:51

3 Answers3

11

It looks like the key is to make your dataset of minimums and maximums by facet group and add geom_blank using that dataset. See this answer for a simple example.

I found that thinking through how to make the limits dataset the challenging part of this. I'll use the mpg dataset to give an example.

First the facets with axes on different scales:

ggplot(mpg, aes(displ, hwy)) +
    geom_point() +
    facet_wrap(~class, scales = "free")

enter image description here

Now, make the dataset of the limits. I do this with functions from dplyr and tidyr. This involves finding the minimum minimum and maximum maximum of the two axis variables for each facet group. I do this in two separate columns, and then gather them into one column. This dataset needs to essentially have identical columns for each axis variable, so I add the duplicate column with the y axis name last.

library(tidyr)
library(dplyr)

facetlims = mpg %>% 
    group_by(class) %>% 
    summarise(min = min(displ, hwy), max = max(displ, hwy)) %>%
    gather(range, displ, -class) %>%
    mutate(hwy = displ, range = NULL)

Source: local data frame [14 x 3]

        class displ   hwy
        (chr) (dbl) (dbl)
1     2seater   5.7   5.7
2     compact   1.8   1.8
3     midsize   1.8   1.8
4     minivan   2.4   2.4
5      pickup   2.7   2.7
6  subcompact   1.6   1.6
7         suv   2.5   2.5
8     2seater  26.0  26.0
9     compact  44.0  44.0
10    midsize  32.0  32.0
11    minivan  24.0  24.0
12     pickup  22.0  22.0
13 subcompact  44.0  44.0
14        suv  27.0  27.0

Now just add geom_blank with this dataset to the original graphic and the axis limits are the same within each facet.

ggplot(mpg, aes(displ, hwy)) +
    geom_point() +
    facet_wrap(~class, scales = "free") +
    geom_blank(data = facetlims)

enter image description here

Community
  • 1
  • 1
aosmith
  • 34,856
  • 9
  • 84
  • 118
  • 1
    Thanks, this is exactly what I wanted. I accepted this answer as it allows for the scales to be the same in each facet while having scales free. I just need to digest the dplyr syntax – user2814482 Sep 14 '15 at 08:13
2

You were close, but the problem is that you are specifying the limits in the wrong way. You should not specify your limits as xlim = range(...). This produces the following error:

Error in range(c(mpg$displ, mpg$hwy)) + facet_wrap(~class, scales = "free") : non-numeric argument to binary operator

The correct way to specify the limits is as xlim(range(...)). An example with the mpg dataset from the ggplot2 package:

ggplot(mpg, aes(displ, hwy)) +
  geom_point() +
  xlim(range(mpg$displ)) + 
  ylim(range(mpg$hwy)) +
  facet_wrap(~class, scales = "free")

which gives:

enter image description here

If you want to compare the different facets the correct way, you will have to use the same scales for the axes.

An alternative to the above plot could be:

ggplot(mpg, aes(displ, hwy)) +
  geom_point(size=1) +
  xlim(range(c(mpg$displ, mpg$hwy))) + 
  ylim(range(c(mpg$displ, mpg$hwy))) +
  facet_wrap(~class, scales = "free")

which gives:

enter image description here


For your own dataset, one of the following two options should give you the desired result:

ggplot(VV,aes(x=R1_Zsc,y=R2_Zsc)) +
  geom_point() +
  stat_smooth() +
  xlim(range(VV$R1_Zsc)) +
  ylim(range(VV$R2_Zsc)) +
  facet_wrap(~variable, scales="free")

or:

ggplot(VV,aes(x=R1_Zsc,y=R2_Zsc)) +
  geom_point() +
  stat_smooth() +
  xlim(range(c(VV$R1_Zsc,VV$R2_Zsc))) +
  ylim(range(c(VV$R1_Zsc,VV$R2_Zsc))) +
  facet_wrap(~variable, scales="free")

If you only want to include the axis-labels on the left facets (y-axis) and the bottom facet (x-axis), just remove scales="free".

Jaap
  • 81,064
  • 34
  • 182
  • 193
  • Thanks, but this isn;t exactly what I wanted as I want x=y but different for each facet, the answer with constructing another dataframe and using geom_blank is what I was looking for – user2814482 Sep 14 '15 at 08:13
1

to produce axes of equal sizes you can put ratio=1 in coord_fixed like this example from ?coord_fixed

library(ggplot2)
qplot(mpg, wt, data = mtcars) + coord_fixed(ratio = 1)
Mamoun Benghezal
  • 5,264
  • 7
  • 28
  • 33
  • Using `coord_fixed` only forces a specified ratio between the physical representation of data units on the axes. However, that is overridden by the `scales="free"` argument in `facet_wrap`. See my answer how to solve the problem, without the need for using `coord_fixed` (which can have unintended consequences for the display of the plot when the limits of both axes do not resemble each other very much). – Jaap Sep 12 '15 at 06:27