Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Color based on difference between bars using ggplot

Tags:

r

I've done quite a bit of searching and am trying to do the following. I have a bar plot with two dodged bars for each value. Each bar represents a percentage. (roughly how it looks as I cannot post images yet)

Feature |XXXXXXXXXXXXXX  %50
        |XXXXXXXX        %25

What I'd like to do is change the color of either of the bars to "RED" whenever the difference in percentage is > 15

Here's the data I'm using:

Feature variable          value
A       "Percent Done"    50
B       "Planned"         25
A       "Percent Done"    10
B       "Planned"         80

Code:

p3 <- ggplot(plotdata, aes(x = Feature, y = value, fill = variable))
p3 <- p3 + geom_bar( position ="dodge", stat ="identity")+ 
      coord_flip() + theme_minimal()

So basically if we looked at the "mock" at the top. Because the percentages between the 2 bars is greater than 15% I'd like one of the bars to be a different color(a third color) like below:

enter image description here

I've thought about using a ifelse to set the color I just haven't been able to implement it. My thinking is using the ifelse to return the color I want to use. So "if" the difference between the 2 bars is > 15 return this color "else" return another color. Does anyone know if this is possible?

like image 317
abemo Avatar asked Feb 25 '26 12:02

abemo


2 Answers

You can create the vector of filling colors prior to your ggplot call.

## Sample data
dat <- data.frame(`Percent Done`=c(25,10,15),
                  Planned=c(50,80,20),
                  Feature=factor(c("A","B","C"), levels=c("C","B","A")))
library(reshape2)
dat <- melt(dat, id.vars = "Feature")  # reshape the data to long format

## Get the fill colors
dat <- dat[order(dat$Feature, dat$variable, decreasing = T), ]
dat$fills <- ifelse(c(0, abs(diff(dat$value))) > 15, "red", "yellow")
dat$fills[c(T,F)] <- "black"

ggplot(dat, aes(Feature, value, group=variable, order=rev(variable))) +
  geom_histogram(stat="identity", aes(fill=fills), position=position_dodge()) +
  scale_fill_manual(values=c("black","red","yellow"), labels=c("Plan",">15%", "Within 15%")) +
  coord_flip() +
  theme_bw()

enter image description here You could probably do this using the hidden variables in the ggplot call as well, but it would be trickier.

like image 151
Rorschach Avatar answered Feb 28 '26 05:02

Rorschach


My answer is in the same lines as @nongkrong:

set.seed(1)
x<-data.frame(feat=letters[1:20],plan=runif(20),exec=runif(20)) # create some dummy data
x$col<-((x$plan-x$exec)>=.15)+1 #create a color column
library(reshape2)
y<-melt(x,id.vars = c("feat","col")) # make it long
y$col[which(y$variable=="plan")]<-0 # create a color difference between planed and executed
y$col<-as.factor(y$col) # make it factor, so we can use it in ggplot
ggplot(y,aes(feat,value,fill=col))+geom_bar(position=position_dodge(),stat="identity")+scale_fill_manual(values=c("black","green","red")) # Create a scale fill with the desired colors
like image 23
PavoDive Avatar answered Feb 28 '26 05:02

PavoDive



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!