Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rotation of facets in ggplot2

Tags:

r

ggplot2

raster

I think I have a tricky case. I'm plotting the evolution plant disease levels in time, using geom_raster: x and y are arbitrary field coordinates, and z is the disease level measured at several time points, and I want to have each date plotted in a different facet. So far, no problem. Below is a mock dataset and code:

library(ggplot2)
data <- data_frame(month=factor(rep(c("march","april","may","june"), each=100), levels=c("march","april","may","june")),
              x=rep(rep(1:10, each=10), 4),
              y=rep(rep(1:10, 10), 4),
              z=c(rnorm(100, 0.5, 1), rnorm(100, 3, 1.5), rnorm(100, 6, 2), rnorm(100, 9, 1)))
ggplot(data, aes(x=x, y=y, fill=z)) +
  geom_raster(color="white") +
  scale_fill_gradient2(low="white", mid=mean(range(dat$z)), high="red") +
  scale_x_discrete(limit=1:10, expand = c(0, 0)) +
  scale_y_discrete(limit=1:10, expand = c(0, 0)) +
  coord_equal() +
  facet_wrap(~month)

But what I'd really like, is to have each facet rotated at a certain angle (for example 15°), to reflect the fact that my field is not oriented perfectly according to north (i.e., the top is not North, and bottom is not South). Is there a possibility in ggplot2, or any grid-related tools, to do this automatically? Even an automatic way to savec individual facets to images, rotate them, and printing the rotated images on new page would be enough for my needs. Here's an example of image I would like to obtain (facets rotated 15° in an image editor): http://imgur.com/RYJ3EaRrotated facets

like image 758
Sebastien Guyader Avatar asked Dec 18 '15 15:12

Sebastien Guyader


1 Answers

Here's a way to rotate the facets independently. We create a list containing a separate rotated plot for each level of month, and then use grid.arrange to lay out the four plots together. I've also removed the legend from the individual plots and plotted the legend separately. The code below includes a helper function to extract the legend.

I extract the legend object into the global environment within the lapply function below (not to mention repeating the extraction multiple times). There's probably a better way, but this way was quick.

library(gridExtra)

# Helper function to extract the legend from a ggplot
# Source: http://stackoverflow.com/questions/12539348/ggplot-separate-legend-and-plot
g_legend<-function(a.gplot){
  tmp <- ggplot_gtable(ggplot_build(a.gplot))
  leg <- which(sapply(tmp$grobs, function(x) x$name) == "guide-box")
  legend <- tmp$grobs[[leg]]
  legend
}

# Create a list containing a rotated plot for each level of month
pl = lapply(unique(data$month), function(m) {

  # Create a plot for the current level of month
  p1 = ggplot(data[data$month==m,], aes(x=x, y=y, fill=z)) +
    geom_raster(color="white") +
    scale_fill_gradient2(low="white", high="red", 
                         limits=c(floor(min(data$z)), ceiling(max(data$z)))) +
    scale_x_discrete(limit=1:10, expand = c(0, 0)) +
    scale_y_discrete(limit=1:10, expand = c(0, 0)) +
    coord_equal() +
    facet_wrap(~month) 

  # Extract legend into global environment
  leg <<- g_legend(p1)

  # Remove legend from plot
  p1 = p1 + guides(fill=FALSE)

  # Return rotated plot
  editGrob(ggplotGrob(p1), vp=viewport(angle=-20, width=unit(0.85,"npc"), 
                                       height=unit(0.85,"npc")))                    
})

# Lay out the rotated plots and the legend and save to a png file
png("rotated.png", 1100, 1000)
grid.arrange(do.call(arrangeGrob, c(pl, ncol=2)),
             leg, ncol=2, widths=c(0.9,0.1))
dev.off()

enter image description here

like image 54
eipi10 Avatar answered Sep 29 '22 13:09

eipi10