Facet with free scales but keep aspect ratio fixed
Asked Answered
M

3

40

I am using ggplot to draw faceted maps and have been unable to work out how to allow "free" scales in each facet (so that small regions don't look too small) while keeping the x-y aspect ratio fixed.

Here is a simplified example:

require(maps)
require(ggplot2)

map_nz <- subset(fortify(map_data('nz')),
                 region %in% c("South.Island ", "North.Island "))
gg_nz <- qplot(long, lat, data=map_nz, geom="polygon", group=group)

I now have a plot of the North and South Islands of New Zealand. I can facet this and display it with a fixed aspect ratio like this:

gg_nz + coord_fixed() + facet_wrap(~region)

with a result that looks like this:

NZ map - fixed aspect ratio

Notice that there is quite a bit of space wasted in the North Island facet. I would like it to take up more of the available space. I can free up the scales like this:

gg_nz + facet_wrap(~region, scales="free")

with the following result:

NZ map - free scales

The problem is that the x-y aspect ratio is no longer 1:1 in each facet. I am happy to have each facet on a different scale, but within the facet I would like to preserve the aspect ratio.

I tried the following without success:

gg_nz + facet_wrap(~region, scales="free") + coord_fixed()

Presumably the scale parameter in facet_wrap overrides coord_fixed. Any suggestions?

UPDATE: to give a more dramatic illustration, here is the same phenomenon with some US states:

Fixed coords (using coord_fixed or coord_equal):

US map - Fixed aspect Free coords (using scales = free):

US map -Free scales

Neither of these maps is ideal: in the first, Delaware is tiny. In the second, the aspect ratios are quite distorted. New Jersey, which is a narrow state, is stretched too wide, for example.

Muddler answered 27/4, 2013 at 23:52 Comment(2)
I think this is what you are looking for: github.com/hadley/ggplot2/issues/187Batts
Certainly looks related (although dealing with a more general problem). Doesn't look solved though!Muddler
F
16

theme(aspect.ratio = 1) works.

gg_nz + facet_wrap(~region, scales="free") + theme(aspect.ratio = 1)

Fulllength answered 30/5, 2017 at 20:18 Comment(2)
interesting. gets a bit complicated picking the right aspect.ratio value when the variables are not numeric, but this does appear to be a possible solution.Smitten
theme(aspect.ratio = 1) sets the aspect of the panel, not the data within it. So if you are plotting with an x range of say 1:10 and y range of 1:1000 aspect.ratio = 1 will set the plot to be square and the actual x axis will be at *10 scale of y axisCestar
B
12

UPDATE:

I believe what you are looking for is the ability to crop or zoom into a single facet. In other words, to adjust the ylims and xlims independently for each facet. It looks like such a feature has been requested but not yet implemented (https://github.com/hadley/ggplot2/issues/187)

If the space=free option below does not work, an alternative is to scrap facets and use grid layouts and/or viewports to print each plot manually.


Using facet_grid instead of facet_wrap and adding space=free:

gg_state + facet_grid(~region, scales = "free_x", space="free")

enter image description here


Original Answer:

maybe instead of having both axis scale freely, just have only one scale:

map_state <- subset(fortify(map_data('state')),
                 region %in% c("california", "nevada"))
gg_state <- qplot(long, lat, data=map_state, geom="polygon", group=group)
gg_state + facet_wrap(~region, scales="free_x")

enter image description here

Batts answered 28/4, 2013 at 1:35 Comment(4)
Still not what I am after: the aspect ratio on the left hand side in particular is quite stretched: about 1:2 rather than 1:1.Muddler
gotcha! essentially you want to crop one facet, not scale it nor stretch it. Just crop.Batts
Sounds about right, although I'd describe it as scaling while preserving the aspect ratio: sort of a zoom and crop.Muddler
Thanks for the updated answer; for my problem a very workable solution.Bonaire
C
0

Does coord_equal help?

 gg_nz + facet_wrap(~region, scales="free") + coord_equal()

Edit

You could use grid.arrange to manually put the plots on a page, fixing the width and height. This seems to do the trick, but I can't make it work with facet() functionality. Thanks to this post from @mnel.

nz_sth <- qplot(long, lat, data=map_nz[map_nz$region == "South.Island ",], geom="polygon", group=group) + coord_fixed()
nz_nth <- qplot(long, lat, data= map_nz[ map_nz$region == "North.Island " , ] , geom="polygon", group=group) + coord_fixed()


grid.arrange( heights=unit(0.75, "npc") , widths=unit(0.5, "npc") , nz_sth,nz_nth, ncol=2)

enter image description here

Cowden answered 27/4, 2013 at 23:55 Comment(4)
coord_equal seems to be a synonym for coord_fixed. I may not have chosen the best example to see the distortion, but if you look at the South Island on your map, there are 2 degrees between gridlines on both axes and the aspect ratio is not 1:1.Muddler
@Muddler hi yes, I see now. I will have a go at this later and see if I can help any.Genipap
Thanks...it's a tricky one. I was hoping for some kind of aspect argument for facet_wrap...Muddler
Error: coord_fixed doesn't support free scalesJoni

© 2022 - 2024 — McMap. All rights reserved.