R: ggplot better gradient color
Solution 1
Thanks @zelite and @SimonO101 for your help. This is simpler version of what both of you proposed. Adding here for the completeness.
library(ggplot2)
library(reshape2)
library(RColorBrewer)
getColors<-function(n){
mypal<-colorRampPalette(brewer.pal(12, "Paired"))
sample(mypal(n), n, replace=FALSE)
}
PropBarPlot<-function(df, mytitle=""){
melteddf<-melt(df, id=names(df)[1], na.rm=T)
n<-length(levels(factor(melteddf$variable)))
ggplot(melteddf, aes_string(x=names(df)[1], y="value", fill="variable")) +
geom_bar(position="fill") +
scale_fill_manual(values=getColors(n)) +
theme(axis.text.x = element_text(angle=90, vjust=1)) +
labs(title=mytitle)
}
df <- data.frame(id=letters[1:3],
val0=1:3,
val1=4:6,
val2=7:9,
val3=2:4,
val4=1:3,
val5=4:6,
val6=10:12,
val7=12:14)
print(PropBarPlot(df))
Thanks.
Solution 2
How about using scale_fill_brewer
which makes use of colour palettes from the ColorBrewer
website, implemented by the package RColorBrewer
?
ggplot(diamonds, aes(clarity, fill=cut) ) +
geom_bar( ) +
scale_fill_brewer( type = "div" , palette = "RdBu" )
There are a number of different diverging palettes you can choose from.
require(RColorBrewer)
?brewer.pal
If you need more colours you can use the colorRampPalette
features to interpolate between some colours (and I would use a brewer.pal
palette for this). You can do this like so:
# Create a function to interpolate between some colours
mypal <- colorRampPalette( brewer.pal( 6 , "RdBu" ) )
# Run function asking for 19 colours
mypal(19)
[1] "#B2182B" "#C2373A" "#D35749" "#E47658" "#F0936D" "#F4A989" "#F8BFA5"
[8] "#FCD6C1" "#F3DDD0" "#E7E0DB" "#DAE2E6" "#CBE1EE" "#ADD1E5" "#90C0DB"
[15] "#72AFD2" "#5B9DC9" "#478BBF" "#3478B5" "#2166AC"
In your example which requires 8 colours you an use it like this with scale_fill_manual()
:
PropBarPlot<-function(df, mytitle=""){
melteddf<-melt(df, id=names(df)[1], na.rm=T)
ggplot(melteddf, aes_string(x=names(df)[1], y="value", fill="variable")) +
geom_bar(position="fill") +
theme(axis.text.x = element_text(angle=90, vjust=1)) +
labs(title=mytitle)+
scale_fill_manual( values = mypal(8) )
}
print(PropBarPlot(df))
Solution 3
Borrowing some code from @SimonO101
library(ggplot2)
library(reshape2)
library(RColorBrewer)
mypal <- colorRampPalette( brewer.pal( 9 , "Set1" ) ) #you can try using different palete instead
#of "Set1" until it looks good to you
intercalate <- function(n){ #my crude attempt to shuffle the colors
c(rbind(1:(n/2), n:(n/2+1))) #it will only work for even numbers
}
PropBarPlot<-function(df, mytitle=""){
melteddf<-melt(df, id=names(df)[1], na.rm=T)
ggplot(melteddf, aes_string(x=names(df)[1], y="value", fill="variable")) +
geom_bar(position="fill") +
theme(axis.text.x = element_text(angle=90, vjust=1)) +
labs(title=mytitle)+
scale_fill_manual( values = mypal(8)[intercalate(8)] )
#better would be to calculate the different number of categories
#you have and put that instead of the number 8
}
df <- data.frame(id=letters[1:3],
val0=1:3,
val1=4:6,
val2=7:9,
val3=2:4,
val4=1:3,
val5=4:6,
val6=10:12,
val7=12:14)
print(PropBarPlot(df))
See if that works better for your needs.
Comments
-
Rachit Agrawal about 2 years
I am using ggplot to plot Proportional Stacked Bar plot. And the Plot I am getting is something like this:
And this is the self written function I am using:
df <- data.frame(id=letters[1:3],val0=1:3,val1=4:6,val2=7:9, val3=2:4, val4=1:3, val5=4:6, val6=10:12, val7=12:14) PropBarPlot<-function(df, mytitle=""){ melteddf<-melt(df, id=names(df)[1], na.rm=T) ggplot(melteddf, aes_string(x=names(df)[1], y="value", fill="variable")) + geom_bar(position="fill") + theme(axis.text.x = element_text(angle=90, vjust=1)) + labs(title=mytitle) } print(PropBarPlot(df))
Here
val4
andval5
are not very different.But due to colors some of them are not distinguishable. Can someone tell me how to choose better colors so that they are differentiable?
Thanks.
-
Rachit Agrawal about 11 yearsI checked the different palettes, the best I get is a max of 12 variation, whereas in my case I need at-least 19 colors. With all the palettes, it is having problem.
-
Simon O'Hanlon about 11 years@RachitAgrawal ok, I updated to something which might work for you. Check the edit.
-
Rachit Agrawal about 11 yearsSuffers from the same problem mentioned above. Some of them cannot be distinguished.
-
Simon O'Hanlon about 11 yearsThen you have too many colour categories in a single plot! The palettes have a maximum number of colours for a reason. Consider splitting your plot using facet_wrap or facet_ grid.
-
zelite about 11 yearsMaybe it would work better if adjacent colors in the plot would be from oposite parts of the palete? In the example you have blues close to blues, and reds close to reds. If they alternate then it would be better distinguished? But I agree with SimonO101: if there's problem distinguishing so many colors, maybe you're plotting too much in one single plot.
-
Rachit Agrawal about 11 yearsI have come up with a simpler solution to mix the colors. Added below. Thanks for the help.