Create a different color scale for each bar in the ggplot2 histogram

I have a summary histogram that looks like this:

The number of patients on each drug by drug class

While the colors look beautiful, it is ridiculous to have so many identical colors representing different drugs. I would like to have a separate color palette for each column in the graph, for example, class1 can use the β€œBlues” palette, while class2 can use the β€œBuGn” palette (the color palette names are found here )

I found some examples where people manually coded colors for each bar (for example, here ), but I'm not sure what I ask for is possible - these bars should be based on palettes, since there are so many drugs in each class of drugs.

Code for creating the above graph:

library(ggplot2) library(plyr) library(RColorBrewer) drug_name <- c("a", "a", "b", "b", "b", "c", "d", "e", "e", "e", "e", "e", "e", "f", "f", "g", "g", "g", "g", "h", "i", "j", "j", "j", "k", "k", "k", "k", "k", "k", "l", "l", "m", "m", "m", "n", "o") df <- data.frame(drug_name) #get the frequency of each drug name df_count <- count(df, 'drug_name') #add a column that specifies the drug class df_count$drug_class <- vector(mode='character', length=nrow(df_count)) df_count$drug_class[df_count$drug_name %in% c("a", "c", "e", "f")] <- 'class1' df_count$drug_class[df_count$drug_name %in% c("b", "o")] <- 'class2' df_count$drug_class[df_count$drug_name %in% c("d", "h", "i")] <- 'class3' df_count$drug_class[df_count$drug_name %in% c("g", "j", "k", "l", "m", "n")] <- 'class4' #expand color palette (from http://novyden.blogspot.com/2013/09/how-to-expand-color-palette-with-ggplot.html) colorCount = length(unique(df_count$drug_name)) getPalette = colorRampPalette(brewer.pal(9, "Set1")) test_plot <- ggplot(data = df_count, aes(x=drug_class, y=freq, fill=drug_name) ) + geom_bar(stat="identity") + scale_fill_manual(values=getPalette(colorCount)) test_plot 
+5
source share
2 answers

The different color palettes above are not sequentially transferred to different classes - instead, they are built in accordance with the specified vector (a, b, c ...) and, thus, are divided into different classes, For more details see ??scale_fill_manual .

To β€œmatch” them with each set of bars, we need to order data.frame by class and align the color palettes with the names accordingly.

Create repeating palettes to verify the correct (expected) ordering.

  repeating.pal = mapply(function(x,y) brewer.pal(x,y), ncol, c("Set2","Set2","Set2","Set2")) repeating.pal[[2]] = repeating.pal[[2]][1:2] # We only need 2 colors but brewer.pal creates 3 minimum repeating.pal = unname(unlist(repeating.pal)) 

Sort data according to class (the order in which we want to save colors!)

  df_count_sorted <- df_count[order(df_count$drug_class),] 

Copy the original medicine name order.

  df_count_sorted$labOrder <- df_count$drug_name 

Add to test color palette.

  df_count$colours<-repeating.pal 

Change the plot procedure, fill = labOrder.

 ggplot(data = df_sorted, aes(x=drug_class, y=freq, fill=labOrder) ) + geom_bar(stat="identity", colour="black", lwd=0.2) + geom_text(aes(label=paste0(drug_name,": ", freq), y=cum.freq), colour="grey20") + scale_fill_manual(values=df_sorted$colours) + guides(fill=FALSE) 

The palette matches the expected order.

+2
source

With so many colors, your plot will be confusing. It is probably best to simply label each section of the bar with the name of the drug and the counter. The code below shows one way to create separate palettes for each bar, as well as how to label columns.

First add the column that we will use to position the hatch shortcuts:

 library(dplyr) # for the chaining (%>%) operator ## Add a column for positioning drug labels on graph df_count = df_count %>% group_by(drug_class) %>% mutate(cum.freq = cumsum(freq) - 0.5*freq) 

Secondly, create palettes. The code below uses four different Colorbrewer palettes, but you can use any combination of functions or palette creation methods to control the colors as accurately as possible.

 ## Create separate palette for each drug class # Count the number of colors we'll need for each bar ncol = table(df_count$drug_class) # Make the palettes pal = mapply(function(x,y) brewer.pal(x,y), ncol, c("BrBG","OrRd","YlGn","Set2")) pal[[2]] = pal[[2]][1:2] # We only need 2 colors but brewer.pal creates 3 minimum pal = unname(unlist(pal)) # Combine palettes into single vector of colors ggplot(data = df_count, aes(x=drug_class, y=freq, fill=drug_name) ) + geom_bar(stat="identity", colour="black", lwd=0.2) + geom_text(aes(label=paste0(drug_name,": ", freq), y=cum.freq), colour="grey20") + scale_fill_manual(values=pal) + guides(fill=FALSE) 

enter image description here

There are many strategies and functions for creating color palettes. Here is another method using the hcl function:

 lum = seq(100, 50, length.out=4) # Vary the luminance for each bar shift = seq(20, 60, length.out=4) # Shift the hues for each bar pal2 = mapply(function(n, l, s) hcl(seq(0 + s, 360 + s, length.out=n+1)[1:n], 100, l), ncol, lum, shift) pal2 = unname(unlist(pal2)) 
+6
source

Source: https://habr.com/ru/post/1244907/


All Articles