2017-04-16 183 views
2

我正在为其中一个较大的项目工作,我在ggplot2中创建了几个图。这些情节关心绘制几个不同的谨慎类别(想想:国家,物种,类型)的几个不同的结果。我想完全修复离散类型到颜色的映射,使Type = A始终显示为红色,Type = B始终显示为蓝色,所有绘图都以不管其他因素如何显示。我知道scale_fill_manual(),我可以手动提供颜色值,然后使用drop = FALSE,这有助于处理未使用的因子水平。但是,我发现这非常麻烦,因为每个情节都需要一些手动工作来处理以正确的方式排序因素,对颜色值进行排序以匹配因子排序,降低未使用的级别等。ggplot2:修复因子水平的颜色

我在寻找的是我可以将一次和全局因子水平映射到特定颜色(A =绿色,B =蓝色,C =红色,...),然后只需绘制任何我喜欢的图和ggplot选择正确的颜色。

下面是一些代码来说明这一点。

# Full set with 4 categories 
df1 <- data.frame(Value = c(40, 20, 10, 60), 
        Type = c("A", "B", "C", "D")) 

ggplot(df1, aes(x = Type, y = Value, fill = Type)) + geom_bar(stat = "identity") 


# Colors change complete because only 3 factor levels are present 
df2 <- data.frame(Value = c(40, 20, 60), 
        Type = c("A", "B", "D")) 

ggplot(df2, aes(x = Type, y = Value, fill = Type)) + geom_bar(stat = "identity") 


# Colors change because factor is sorted differently 
df3 <- data.frame(Value = c(40, 20, 10, 60), 
        Type = c("A", "B", "C", "D")) 
df3$Type <- factor(df3$Type, levels = c("D", "C", "B", "A"), ordered = TRUE) 

ggplot(df3, aes(x = Type, y = Value, fill = Type)) + geom_bar(stat = "identity") 

回答

3

你可以做一个自定义的绘图功能(包括scale_fill_manual和合理的默认颜色),以避免重复代码:

library(ggplot2) 
custom_plot <- function(.data, 
    colours = c("A" = "green", "B" = "blue", "C" = "red", "D" = "grey")) { 
    ggplot(.data, aes(x=Type, y=Value, fill= Type)) + geom_bar(stat="identity") + 
    scale_fill_manual(values = colours) 
} 

df1 <- data.frame(Value=c(40, 20, 10, 60), Type=c("A", "B", "C", "D")) 
df2 <- data.frame(Value=c(40, 20, 60), Type=c("A", "B", "D")) 
df3 <- data.frame(Value=c(40, 20, 10, 60), Type=c("A", "B", "C", "D")) 
df3$Type <- factor(df3$Type, levels=c("D", "C", "B", "A"), ordered=TRUE) 

custom_plot(df1) 
custom_plot(df2) 
custom_plot(df3) 
+0

AH!所以scale_fill_manual()*可以*处理命名向量!这正是我所期待的。谢谢Kristoffer。 – Chris

2

你可以定义自己的规模,如果你喜欢。如果你看一下源scale_fill_manual

scale_fill_manual 
#> function (..., values) 
#> { 
#>  manual_scale("fill", values, ...) 
#> } 
#> <environment: namespace:ggplot2> 

它实际上很简单:

library(ggplot2) 

scale_fill_chris <- function(...){ 
    ggplot2:::manual_scale('fill', 
          values = setNames(c('green', 'blue', 'red', 'orange'), 
              LETTERS[1:4]), 
          ...) 
} 

df1 <- data.frame(Value = c(40, 20, 10, 60), 
        Type = c("A", "B", "C", "D")) 

ggplot(df1, aes(x = Type, y = Value, fill = Type)) + 
    geom_col() + 
    scale_fill_chris() 

df2 <- data.frame(Value = c(40, 20, 60), 
        Type = c("A", "B", "D")) 

ggplot(df2, aes(x = Type, y = Value, fill = Type)) + 
    geom_col() + 
    scale_fill_chris() 

df3 <- data.frame(Value = c(40, 20, 10, 60), 
        Type = c("A", "B", "C", "D")) 
df3$Type <- factor(df3$Type, levels = c("D", "C", "B", "A"), ordered = TRUE) 

ggplot(df3, aes(x = Type, y = Value, fill = Type)) + 
    geom_col() + 
    scale_fill_chris()