为ggplot2堆积条形图中的每个条形创建不同的颜色比例

时间:2016-03-11 18:08:55

标签: r ggplot2 bar-chart color-palette

我有一个堆积的条形图,如下所示:

Number of patients on each drug by drug class

虽然颜色看起来不错,但是有很多相似的颜色代表不同的药物会令人困惑。我想为图中的每个条形图分别设置一个调色板,例如,class1可以使用调色板“Blues”,而class2可以使用调色板“BuGn”(调色板名称找到here

我找到了一些人们为每个栏手动编码颜色的例子(例如here),但我不确定我问的是否可能 - 这些栏需要基于调色板,因为每个药物类别都有这么多的药物。

创建上图的代码:

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

2 个答案:

答案 0 :(得分:6)

如此多的颜色,你的情节将会令人困惑。用药物名称和计数标记每个条形部分可能更好。下面的代码显示了为每个条形图制作单独调色板的一种方法,以及如何标记条形图。

首先,添加一个我们将用于定位条形标签的列:

$query = $this->db->query("select * from mytbl"); 

if ($query->num_rows() > 0)
{
   foreach ($query->result() as $row)
   {
      echo $row->title;
      echo $row->name;
      echo $row->body;
   }
}  

其次,创建调色板。下面的代码使用了四种不同的Colorbrewer调色板,但您可以使用调色板创建功能或方法的任意组合来精确控制颜色。

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)

enter image description here

创建调色板有许多策略和功能。这是另一种方法,使用## 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) 函数:

hcl

答案 1 :(得分:2)

上面的各种调色板不会一致地转移到不同的类 - 相反,它们根据命名的矢量(a,b,c ...)进行绘制,因此在各个类之间进行分割。有关详细信息,请参阅??scale_fill_manual

为了将它们“匹配”到每组条形图,我们需要按类别对data.frame进行排序,并将颜色调色板与名称对齐。

创建重复调色板以测试正确(预期)排序。

 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))

根据类别排序数据(我们希望颜色保留的顺序!)

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

复制药品名称的原始订单。

 df_count_sorted$labOrder <- df_count$drug_name

添加测试调色板。

 df_count$colours<-repeating.pal

使用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)

Palette follows expected order