Fox
Fox

Reputation: 33

How can I align a map plot and a boxplot that share a y-axis

I am trying to align or combine a map and a boxplot, both of which have latitude as their y-axis. I've found a number of ways to align plots, but it seems like having a map involved complicates things. I'd like to have the two plots align seamlessly, with the map on the left and boxplot on the right.

Here's example code for the two plots:

library(ggplot2)
library(maps)
library(gridExtra)

##Plot base map
s_map <- map_data('state',region=c('south carolina','georgia','florida'))
p <- ggplot() + coord_fixed()
base_world <- p+geom_polygon(data=s_map, aes(x=long, y=lat, group=group), color="white", fill="grey72")

yscale <- c(24:34)

map1 <- base_world +
  coord_map(xlim = c(-83, -79.5),ylim = c(25, 34)) +
  xlab("") + 
  ylab("Latitude") +
  scale_y_discrete(labels=yscale)

##plot boxplot   (seasonal movements of an animal)
df <- data.frame("month"=month.abb,
                   "min"=c(26,26,26,28,28,29,29,29,28,28,26,26),
                   "lci"=c(27,27,27,29,29,30,30,30,29,29,27,27),
                   "med"=c(28,28,28,29,29,31,31,31,29,29,28,28),
                   "uci"=c(29,29,29,30,30,32,32,32,30,30,29,29),
                   "max"=c(30,30,30,31,31,33,33,33,31,31,30,30),
                    "order"=c(1:12))

boxplot1 <- ggplot(df, aes(x=factor(order), ymin = min, lower = lci, middle = med, upper = uci, ymax = max)) +
  geom_boxplot(stat = "identity") +
  ggtitle("Latitude by Month") +
  xlab("Month") + 
  ylab("Latitude") +
  ylim(24,33)

  grid.arrange(map1,boxplot1,ncol=2)

How do I force the y-axes and plot heights to be the same, with gridlines aligned?

Thanks in advance for your thoughts on this - I'm still pretty new with R.

EDITED: I've tried probably a dozen fragments of code I found, and nothing much seemed effective at all, so I didn't think listing them would be helpful. I'm mostly looking for a real place to start.

Here's one example I found for forcing plot heights to be the same, but it didn't seem to do anything:

# build the plots 
    map2 <- ggplot_gtable(ggplot_build(map1))
    boxplot2 <- ggplot_gtable(ggplot_build(boxplot1))

# copy the plot height from p1 to p2
boxplot2$heights <- map2

grid.arrange(map2,boxplot2,ncol=2,widths=c(1,5))

Upvotes: 3

Views: 877

Answers (1)

erc
erc

Reputation: 10131

This might work for you, I changed three things:

  • added ggtitle("") to the map
  • added theme(plot.margin()) to both plots to change the space around the plots (you can play with the values)
  • added scale_y_continuous(limits=c(24,33), breaks=seq(24,33,by=1), expand=c(0,0)) to the plot in order to create same axis scale as for the map

List item

map1 <- base_world +
  coord_map(xlim = c(-83, -79.5),ylim = c(25, 34)) +
  xlab("") + 
  ylab("Latitude") +
  scale_y_discrete(labels=yscale) +
  ggtitle("") +
  theme(plot.margin=unit(c(0.5,-1.5,0.5,-8), "cm"))

boxplot1 <- ggplot(df, aes(x=factor(order), ymin = min, lower = lci, middle = med, upper = uci, ymax = max)) +
  geom_boxplot(stat = "identity") +
  ggtitle("Latitude by Month") +
  xlab("Month") + 
  ylab("Latitude") +
  scale_y_continuous(limits=c(24,33), breaks=seq(24,33,by=1), expand=c(0,0)) +
  labs(y=NULL) +
  theme(plot.margin=unit(c(0.5,0.5,0.5,-6), "cm"))

grid.arrange(map1,boxplot1,ncol=2)

Upvotes: 1

Related Questions