ggplot - geom_point: setting manual fill color for point jitter without changing boxplot fill color

53 Views Asked by At

I've been generating a grouped boxplot to show the data corresponding to two parameters (deltaF and deltaD) quantified for three 'samples' (aDM31_WT, bDM75_WT, cDM31_NS). for aDM31_WT and bDM75_WT, there's plenty of replicates, so I'm showing a boxplot with point jitter. For cDM31_NS, there's only 2 replicates, so I'm only showing the individual datapoints, and no boxplot.

enter image description here

I want the 4 jitter points for cDM31_NS to have a BLUE fill. whilst all other costum colors remains unchanged. I haven't been able to figure out how.

here's my code:

library(dplyr)
library(ggplot2)

test <- read.table("Fig3G.txt", header = T)
attach(test)
names(test)

graph2 <- ggplot(test, aes(x = parameter, y = value, fill = sample, color = sample)) +
  scale_color_manual(values = c("black", "black", "white", "black", "black", "white")) +
  stat_boxplot(geom = "errorbar", position = position_dodge(width = 0.75), width = 0.2, show.legend = FALSE) +
  scale_fill_manual(values = c("#FFFFFF", "#CC6633", "#FFFFFF", "#FFFFFF", "#CC6633", "#FFFFFF")) +
  scale_y_continuous(position = "right", limits = c(-160, 0)) +
  geom_boxplot(outlier.shape = NA, show.legend = TRUE) +
  scale_x_discrete(limits = c("deltaF", "deltaD")) +
  geom_point(color = "black", size = 0.9, alpha = 0.4, show.legend = FALSE, position = position_jitterdodge(jitter.width = 0.2)) +
  theme(legend.position = "none") +
  theme_linedraw() +
  theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank())

graph2

I've tried setting a seperate scale_fill_manual code to te geom_point function, but it simply applies any change in color to the boxplot fills too.

2

There are 2 best solutions below

0
vgilbart On BEST ANSWER

I believe this could help: Allowing for different colors for boxplot and overlying points in ggplot2

So the following should work in your case:

library(ggnewscale)

graph2 <- ggplot(test, aes(x = parameter, y = value, fill = sample, color = sample)) +
  scale_color_manual(values = c("black", "black", "white", "black", "black", "white")) +
  stat_boxplot(geom = "errorbar", position = position_dodge(width = 0.75), width = 0.2, show.legend = FALSE) +
  scale_fill_manual(values = c("#FFFFFF", "#CC6633", "#FFFFFF", "#FFFFFF", "#CC6633", "#FFFFFF")) +
  scale_y_continuous(position = "right", limits = c(-160, 0)) +
  geom_boxplot(outlier.shape = NA, show.legend = TRUE) +
  scale_x_discrete(limits = c("deltaF", "deltaD")) +
  ## Solution begins
  new_scale_color() +
  geom_point(aes(color = sample), size = 0.9, alpha = 0.4, show.legend = FALSE, position = position_jitterdodge(jitter.width = 0.2)) +
  scale_color_manual(values = c("black", "black", "blue", "black", "black", "blue"))
  ## Solution ends
  theme(legend.position = "none") +
  theme_linedraw() +
  theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank())

graph2
0
stefan On

Here is one approach to achieve your desired result using named vector of colors for both fill and color and which uses after_scale to get rid of the boxplot outlines for the "cDM31_NS" category.

Using some fake random example data:

library(ggplot2)

set.seed(123)

# Example data
test <- expand.grid(
  sample = c("aDM31_WT", "bDM75_WT", "cDM31_NS"),
  parameter = c("deltaF", "deltaD"),
  id = seq(50)
) |>
  transform(value = runif(150, -150, 0))

pal_color <- c("black", "black", "blue")
pal_fill <- c("white", "#CC6633", "transparent")
names(pal_fill) <- names(pal_color) <- c("aDM31_WT", "bDM75_WT", "cDM31_NS")

ggplot(test, aes(
  x = parameter, y = value, fill = sample
)) +
  stat_boxplot(
    aes(color = after_scale(
      ifelse(fill == "transparent", NA, "black")
    )),
    geom = "errorbar",
    position = position_dodge(width = 0.75), width = 0.2,
    show.legend = FALSE
  ) +
  geom_boxplot(
    aes(color = after_scale(
      ifelse(fill == "transparent", NA, "black")
    )),
    outlier.shape = NA, 
    show.legend = TRUE
  ) +
  geom_point(
    aes(color = sample),
    size = 0.9, alpha = 0.4, show.legend = FALSE,
    position = position_jitterdodge(jitter.width = 0.2)
  ) +
  scale_x_discrete(limits = c("deltaF", "deltaD")) +
  scale_y_continuous(position = "right", limits = c(-160, 0)) +
  scale_color_manual(
    values = pal_color, guide = "none"
  ) +
  scale_fill_manual(
    values = pal_fill
  ) +
  theme(legend.position = "none") +
  theme_linedraw() +
  theme(
    panel.grid.major = element_blank(),
    panel.grid.minor = element_blank()
  )