is there a way to change the color palette for GGally::ggpairs using ggplot?
Turns out, this is possible! It requires looking up the source code, but the solution comes up pretty easily. We are interested in ggpairs
function, so the first step is just
ggpairs
Let's see if we can find any aes mapping to fill or colour. Indeed,
combo_aes <- addAndOverwriteAes(aes_string(x = xColName,
y = yColName, ...), section_aes)
We may hope it does what it says. Two important notes:
colour and fill aes should be contained in the ellipsis for the
ggpairs
callaes_string()
is used
Let's try this out:
ggpairs(diamonds[, 1:2], colour='cut')
Excellent, we're almost there! We just need to override the colour palette. Note that something like you propose
ggpairs(diamonds[, 1:2], colour='cut') + scale_fill_brewer(palette = "Set2")
will not work because ggpairs object is not a ggplot, so the +
notation is not directly applicable in any way. However, the simple workaround is provided here. Cross your fingers, and...
ggplot <- function(...) ggplot2::ggplot(...) + scale_fill_brewer(palette="Set2")
ggpairs(diamonds[, 1:2], colour='cut')
update:
GGAlly was updated again and the hack in this answer also doesn’t work anymore, but finally there’s a non-hack solution: given
scales <- scale_colour_brewer(type = 'qual') %+% scale_fill_brewer(type = 'qual')
you can do (in a hopefully future-proof way)
for (row in seq_len(ps$nrow))
for (col in seq_len(ps$ncol))
ps[row, col] <- ps[row, col] + scales
old way
The hack in the other answer does not work anymore, so let’s hack a new one!
The internal structure of a ggpairs
object is the dataset and a list of strings:
> dta <- data.frame(a=1:6, b=7:12, c=c('f', 'g'))
> ps <- ggpairs(dta, 1:2, colour = 'c')
> str(ps)
List of 10
$ data :'data.frame': 2 obs. of 3 variables:
..$ a: int [1:2] 1 2
..$ b: int [1:2] 3 4
..$ c: int [1:2] 5 6
$ columns : int [1:3] 1 2 3
$ plots :List of 9
..$ : chr "ggally_densityDiag(ggally_data, ggplot2::aes(x = a, colour = c))"
..$ : chr "ggally_cor(ggally_data, ggplot2::aes(x = b, y = a, colour = c))"
[...]
$ gg : NULL
- attr(*, "class")= chr [1:2] "gg" "ggpairs"
> ps
In order to modify the plot, the respective strings in the plot object need to be modified to include the additional command. For this, we use deparse(substitute(argument))
to get a string containing the code the user passed, and append it to every plot call:
add_to_plots <- function(pairs, modification) {
str <- deparse(substitute(modification))
pairs$plots <- lapply(pairs$plots, function(s) paste(s, '+', str))
pairs
}
> add_to_plots(ps, scale_colour_brewer(type = 'qual'))
I feel like the most non-hacky way to change the palette is to modify its own graphing function since they return ggplot2 objects which can be customized freely.
To change the density in the diagonal, just change the corresponding function, ggally_densityDiag
.
modified_density = function(data, mapping, ...) {
ggally_densityDiag(data, mapping, ...) + scale_fill_brewer(type = "qual", palette = "Set2")
}
Then, provide the new function to ggparis
function call, as below,
ggpairs(iris, columns = 1:3, aes(color = Species),
diag = list(continuous = modified_density))
There are upper
and lower
arguments that can be used for other parts of the plot as well.