Manually Colouring Plots with 'Scale_Fill_Manual' in Ggplot2 Not Working

Manually colouring plots with `scale_fill_manual` in ggplot2 not working

Just in case you are not sure what @baptise means:

ggplot(ServicesProp, aes(x = Service, y = percent, fill = Service)) + 
geom_bar(stat = "identity", position = "dodge") +
scale_fill_manual(values = c("red", "grey", "seagreen3"))

Sample Image

Scale_fill_manual not producing color fill specified by a condition

Try changing fill by color. Bars can be filled, whereas dots as those in jitter can be colored:

library(ggplot2)
#Data
fileUrl <- "https://raw.githubusercontent.com/MichaelSodeke/DataSets/main/tornado_dmg.csv"
df2 <- read.csv(fileUrl)
#Code
ggplot(df2, aes(x=bgn.date, y=path.area, color=(f == 5) ))+
geom_jitter(stat="identity", size=1)+
scale_color_manual(values=c("TRUE"="red", "FALSE"="grey80"))

Output:

Sample Image

How to use scale_fill_manual to manually define bar plot colors

I would create a dummy variable in your input df2 for the ggplot fill aesthetic. Here, "-999" refers to "OJ" and will be coloured in black.

I've also updated your myPalette to include black in it, and also setNames to it so that only "-999" will have a corresponding "black" value.

library(tidyverse)

df2 <- data.frame(supp=rep(c("VC", "OJ"), each=3),
dose=rep(c("D0.5", "D1", "D2"),2),
len=c(6.8, 15, 33, 4.2, 10, 29.5))

myPalette <- c("#05eb92", "#119da4", "#ffc857")

myPalette_with_black <- setNames(c(myPalette, "black"),
c(as.character(seq_along(myPalette)), "-999"))

df2 <- df2 %>%
group_by(supp) %>%
mutate(dummy = ifelse(supp == "VC", as.character(row_number()), "-999"))

ggplot(data=df2, aes(x=dose, y=len, fill = dummy)) +
geom_bar(stat="identity", position=position_dodge()) +
scale_fill_manual(values = myPalette_with_black) +
theme(legend.position = "none")

Sample Image

Created on 2022-03-12 by the reprex package (v2.0.1)

scale_fill_manual is only applying to the legend and not bars

The issue is that your column p_value_dif does not contain any values "Significant" or "Insignificant". Only these values will be filled "black" or "orange". All other values will be filled with the default na.value of the scale. Instead you could map your column p-value.category on fill and set your fill colors and labels like so:

library(ggplot2)

ggplot(df, aes(x=gene,
y=p_value_dif ,
label=p_value_dif )) +
geom_bar(stat='identity',
aes(fill= `p-value.category`),
width=0.9) +
scale_fill_manual("legend",
values = c("sig" = "black", "non-sig" = "orange"),
labels = c("sig" = "Significant", "non-sig" = "Insignificant"))+
coord_flip()

Sample Image

DATA

df <- data.frame(
stringsAsFactors = FALSE,
check.names = FALSE,
gene = c("a", "c", "d", "e"),
p_value = c(0.06, 0.07, 0.008, 0.009),
p_value_dif = c("0.01", "0.02", "- 0.03", "- 0.04"),
`p-value.category` = c("non-sig", "non-sig", "sig", "sig")
)

ggplot2 displays wrong colors with manual scale

The reason you are getting different colours I think is because ggplot isn't automatically making a connection between the colours you have supplied and the groups you have supplied. I'm not 100% sure why this is the case, but I can offer a solution.

You can create a new column in the data before you send it to ggplot for plotting. We will call it colour_group but you can call it anything. We populate this new column based on the values of avg (I have made sample data as you haven't supplied all of yours). We use ifelse() which tests a condition against the data, and returns a value based on if the test is TRUE or FALSE.

In the below code, colour_group = ifelse(avg < -0.01, 'red', NA) may be read aloud as: "If my value of avg is less than -0.01, make the value for the colour_group column 'red', otherwise make it NA". For subsequent lines, we want the FALSE result to keep the results already in the colour_group column - the ones made on the previous lines.

# make sample data
tibble(
chunk = 1:100,
avg = rnorm(100, 1, 1)
) %>%
{. ->> my_data}

# make the new 'colour_group' column
my_data %>%
mutate(
colour_group = ifelse(avg < -0.01, 'red', NA),
colour_group = ifelse(avg > 0.01, 'green', colour_group),
colour_group = ifelse(avg > -0.01 & avg < 0.01 , 'yellow', colour_group),
) %>%
{. ->> my_data_modified}

Now we can plot the data, and specify that we want to use the colour_group column as the fill aesthetic. When specifying scale_fill_manual, we then tell ggplot that if we have the value of green in the colour_group column, we want the bar to be a green colour, and so on for the other colours.

my_data_modified %>%
ggplot(aes(chunk, avg, fill = colour_group))+
geom_bar(stat = 'identity', show.legend = FALSE)+
scale_fill_manual(
values = c('green' = 'green', 'red' = 'red', 'yellow' = 'yellow')
)

Sample Image

It is slightly confusing, in a way having to specify the colour twice. However, we could specify the values of colour_group as anything, such as 1, 2, 3 or low, med, high. In this instance, you would do the same code but modify the ifelse statements, and change scale_fill_manual to match these values. For example:

my_data %>%
mutate(
colour_group = ifelse(avg < -0.01, 'low', NA),
colour_group = ifelse(avg > 0.01, 'high', colour_group),
colour_group = ifelse(avg > -0.01 & avg < 0.01 , 'med', colour_group),
) %>%
{. ->> my_data_modified}

my_data_modified %>%
ggplot(aes(chunk, avg, fill = colour_group))+
geom_bar(stat = 'identity', show.legend = FALSE)+
scale_fill_manual(
values = c('high' = 'green', 'low' = 'red', 'med' = 'yellow')
)

Sample Image

R assigning colors manually in ggplot

You can pass a named vector to scale_fill_manual :

library(ggplot2)

ggplot(test1, aes(y = rn, x = variable, fill = value)) +
geom_tile() +
theme(strip.background = element_blank(),
strip.text.x = element_blank(),
text = element_text(size=3)) +
geom_text(aes(label=value), size=3) +
labs(x="Seg", y= "Id ", fill = "Div",
title= "Myplot")+
scale_fill_manual(values=setNames(color, test1$value))


Related Topics



Leave a reply



Submit