2

I would like to change the colour of the bars of the histogram on a pairs plot whereby I have a different colour for each variable. It appears I can change the colour of ALL diagonal histograms by changing the 'fill =' option to a new colour but when I attempt to substitute a list of four colours I get the error report:

"r: Aesthetics must be either length 1 or the same as the data (15): fill"

So it seems the colours are somehow linked to the number of bins specified for the histograms not the fill colour for each histogram?

What is the best way to achieve a different colour for each histogram on the diagonal?

Example code below:

require(GGally)

# function for scatter plots with smoothed trend line
lower_plots <- function(data, mapping, ...) {
  ggplot(data = data, mapping = mapping) +
    geom_point(color = "black", shape = 1, size = 1, alpha = 1) +
    geom_smooth(method = "gam",...) 
} 

# colour palette for histograms - subsitue for fill = ?
clrs <- c("red","green","blue","orange")

# pairs plot
ggpairs(iris,1:4, 
        diag = list(continuous = wrap("barDiag", bins = 15, fill = "blue")),
        lower = list(continuous = wrap(lower_plots, color="red", se=F))) +
  theme_light(base_size = 12) +                                                                                                                 
  theme_light(base_size = 12) +                                                                                                                 
  scale_fill_manual(values = ZNS[order(ZNS$Zone), 4])  +                                                                                         
  theme(panel.grid.minor = element_blank(), panel.grid.major = element_blank()) +
  theme(plot.margin = unit(c(2.5,2.5,2.5,3.5), "lines")
  ) 

enter image description here

Markm0705
  • 1,340
  • 1
  • 13
  • 31

1 Answers1

2

I found a work arround for your problem by using global assignment from inside of a function. First I though it was not possible due to the lack of beeing able to identify in one column of the input how to color the histograms, as each line contains multiple observations... I tested a bit and wondered, that given the fact of everything beeing processed in batches/loops, global assignment would help - and it does:

require(GGally)

# function for scatter plots with smoothed trend line
lower_plots <- function(data, mapping, ...) {
    ggplot(data = data, mapping = mapping) +
        geom_point(color = "black", shape = 1, size = 1, alpha = 1) +
        geom_smooth(method = "gam",...) 
} 

# working with a trick of global assignment
diag_plots <- function(data, mapping, ...) {
    # increase counter each run globally so outside the function as well and this does the trick!
    x <<- x + 1
    ggplot(data = data, mapping = mapping) +
        # choose color by counter and send bin width argument in
        geom_histogram(fill = clrs[x], ...)
} 

# set the color and counter
clrs <- c("red","green","blue","orange")
x <- 0

# pairs plot
ggpairs(iris,1:4, 
        diag = list(continuous = wrap(diag_plots, bins = 15)),
        lower = list(continuous = wrap(lower_plots, color="red", se=FALSE))) +
        theme_light(base_size = 12) + 
        theme_light(base_size = 12) + 
        theme(panel.grid.minor = element_blank(), panel.grid.major = element_blank()) +
    theme(plot.margin = unit(c(2.5,2.5,2.5,3.5), "lines")) 

enter image description here

DPH
  • 4,244
  • 1
  • 8
  • 18
  • Nice - I don't fully understand the and have not seen this 'x <<- x + 1' syntax before. Is this a method of invoking loops inside a function? – Markm0705 Jul 28 '21 at 05:17
  • 1
    the <<- operator makes sure that the content from inside the function (aka function environment) are available outside the function (global environment). The explanation is a bit complex there here goes a link: https://excelquick.com/r-programming/assignment-operators-in-r/ – DPH Jul 28 '21 at 10:34
  • You can grab the mapping variable and use it in a lookup to avoid calling in to the global env. e.g. set colour vector like `clrs <- setNames(c("red","green","blue","orange"), names(iris[1:4]))` and define the function as `diag_plots <- function(data, mapping, clrs, ...) { ggplot(data = data, mapping = mapping) + geom_histogram(fill = clrs[rlang::as_name(mapping$x)], ...)}` then in the call use `wrap(diag_plots, clrs=clrs, bins = 15)` – user20650 Sep 24 '21 at 01:51