Different legends and fill colours for facetted ggplot?

At the risk of stating the obvious, it seems like you should be coloring by percents instead of raw values. Then your transformed values and your legend go from 0 to 1.


Currently there can be only one scale per plot (for everything except x and y).


With grid goodness

align.plots <- function(..., vertical=TRUE){
#http://ggextra.googlecode.com/svn/trunk/R/align.r
  dots <- list(...)
  dots <- lapply(dots, ggplotGrob)
  ytitles <- lapply(dots, function(.g) editGrob(getGrob(.g,"axis.title.y.text",grep=TRUE), vp=NULL))
  ylabels <- lapply(dots, function(.g) editGrob(getGrob(.g,"axis.text.y.text",grep=TRUE), vp=NULL))
  legends <- lapply(dots, function(.g) if(!is.null(.g$children$legends))
                    editGrob(.g$children$legends, vp=NULL) else ggplot2:::.zeroGrob)

  gl <- grid.layout(nrow=length(dots))
  vp <- viewport(layout=gl)
  pushViewport(vp)
  widths.left <- mapply(`+`, e1=lapply(ytitles, grobWidth),
                        e2= lapply(ylabels, grobWidth), SIMPLIFY=F)
  widths.right <- lapply(legends, function(g) grobWidth(g) + if(is.zero(g)) unit(0, "lines") else unit(0.5, "lines")) # safe margin recently added to ggplot2
  widths.left.max <- max(do.call(unit.c, widths.left))
  widths.right.max <- max(do.call(unit.c, widths.right))

  for(ii in seq_along(dots)){
    pushViewport(viewport(layout.pos.row=ii))
    pushViewport(viewport(x=unit(0, "npc") + widths.left.max - widths.left[[ii]],
                          width=unit(1, "npc") - widths.left.max + widths.left[[ii]] -
                                                 widths.right.max + widths.right[[ii]],
                          just="left"))
    grid.draw(dots[[ii]])
  upViewport(2)
  }
}



p <- ggplot(datapoly[datapoly$variable=="val1",], aes(x=x, y=y)) + geom_polygon(aes(fill=value, group=id),colour="black")
p1 <- ggplot(datapoly[datapoly$variable=="val2",], aes(x=x, y=y)) + geom_polygon(aes(fill=value, group=id),colour="black")
align.plots( p,p1)

Revisiting this question more than 10 years later, the excellent ggnewscale package solves the problem of having multiple colour scales. Caveat is that you'd need two seperate layers for your facet data, so you'd have to break it up a bit. The order in which new scales are added to the plot matters, so I recommend the order 'layer - scale - new_scale - layer - scale'. Subsequent new scales should repeat the 'new_scale - layer - scale' pattern.

library(ggplot2)
library(ggnewscale)

ids <- factor(c("1.1", "2.1", "1.2", "2.2", "1.3", "2.3"))
values <- data.frame(
  id = ids,
  val1 = cumsum(runif(6, max = 0.5)),
  val2 = cumsum(runif(6, max = 50))
)
positions <- data.frame(
  id = rep(ids, each = 4),
  x = c(2, 1, 1.1, 2.2, 1, 0, 0.3, 1.1, 2.2, 1.1, 1.2, 2.5, 1.1, 0.3,
        0.5, 1.2, 2.5, 1.2, 1.3, 2.7, 1.2, 0.5, 0.6, 1.3),
  y = c(-0.5, 0, 1, 0.5, 0, 0.5, 1.5, 1, 0.5, 1, 2.1, 1.7, 1, 1.5,
        2.2, 2.1, 1.7, 2.1, 3.2, 2.8, 2.1, 2.2, 3.3, 3.2)
)

values <- reshape2::melt(values)
#> Using id as id variables
datapoly <- merge(values, positions, by=c("id"))

ggplot(datapoly, aes(x=x, y=y)) + 
  geom_polygon(aes(fill=value, group=id),
               data = ~ subset(., variable == "val1"),
               colour="black") +
  scale_fill_distiller(palette = "Reds") +
  new_scale_fill() +
  geom_polygon(aes(fill=value, group=id),
               data = ~ subset(., variable == "val2"),
               colour="black") +
  scale_fill_distiller(palette = "Greens") +
  facet_wrap(~ variable)

Created on 2021-02-12 by the reprex package (v1.0.0)