ggplot2:将颜色固定到因子水平

Posted

技术标签:

【中文标题】ggplot2:将颜色固定到因子水平【英文标题】:ggplot2: Fix colors to factor levels 【发布时间】:2017-09-12 09:32:35 【问题描述】:

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

我正在寻找一种方法,我可以将一次全局因子级别映射到特定颜色(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")

【问题讨论】:

【参考方案1】:

确保先将该列转换为Factor,然后创建一个变量来存储每个因子的颜色值...

df$color <- as.factor(df$color, levels = c(1, 0))
cbPallete <- c("1"= "green", "0"="red")

ggplot(data = df) + geom_bar(x = df$x, 
                             y = df$y,
                             fill = df$color) +
scale_fill_manual(values = cbPallete)

【讨论】:

【参考方案2】:

另一种选择是通过如下定义默认色标使drop = F 成为默认值:

scale_colour_discrete <- function(...)
  scale_colour_manual(..., drop = F)
scale_fill_discrete <- function(...)
  scale_fill_manual(..., drop = F)

这样颜色对于不同的因素总是一致的。

【讨论】:

【参考方案3】:

如果您愿意,您可以定义自己的自定义比例。如果您查看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()

【讨论】:

【参考方案4】:

您可以制作自定义绘图功能(包括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)

【讨论】:

啊!所以 scale_fill_manual() 可以 处理命名向量!这正是我一直在寻找的。谢谢克里斯托弗。

以上是关于ggplot2:将颜色固定到因子水平的主要内容,如果未能解决你的问题,请参考以下文章

ggplot2:从图中删除未使用的因子水平组合的方面(facet_grid)

R语言ggplot2可视化柱状图(条形图)可视化中保留没有用到的因子水平(占位保留)

使用 `scale_colour_manual` 或替代方法(有时)缺少因子水平时,`ggplot2` 中的一致着色

R语言ggplot2可视化:使用ggplot2按照热力图的方式显示全是分类变量的dataframe数据并自定义因子(factor)的图例颜色legend

将水平线添加到 R 中 ggplot2 中的堆叠条形图,并在图例中显示

绘制水平条形图的给定颜色并使用 ggplot2 将未绘制区域用灰色着色