This solution is not as universal as we might want, but it is also not very difficult and technical. First, some data:
y <- c(5, 2, 3, 2) x <- factor(c("A", "B", "C", "A")) z <- factor(c("D", "E", "F", "E")) p <- qplot(x, y, geom = "point") + theme(axis.text.x = element_text(color = z))
The popular g_legend function (can be found, for example, here ) is useful in this case, it accepts the legend from the plot as (therefore, this decision is not fast).
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 }
So, we save two legends: one for the points ( x ) and one for the x ( z ) axis.
legends <- list(g_legend(p + geom_point(aes(color = x))), g_legend(p + geom_point(aes(color = z)) + scale_color_manual(values = palette()[as.numeric(z)])))
Note the difference in the second legend. palette() used here because, for example, if z <- factor(c(1, 2, 3)) , then element_text(color = z) uses different colors than geom_point(aes(color = z)) , those. element_text(color = z) accepts colors from the base graph, for example. 2 in plot(1, col = 2) .
Finally, all together:
library(gridExtra) grid.arrange(p + geom_point(aes(color = x)) + guides(color = 'none'), do.call(arrangeGrob, legends), nrow = 1, widths = c(0.8, 0.2))
