如何为具有稳定映射的ggplot2中的分类变量分配颜色?


176

在上个月,我一直在跟上R的发展。

这是我的问题:

为ggplot2中具有稳定映射的分类变量分配颜色的好方法是什么?我需要一组具有不同子集和不同数量类别变量的图形具有一致的颜色。

例如,

plot1 <- ggplot(data, aes(xData, yData,color=categoricaldData)) + geom_line()

那里categoricalData有5个等级。

然后

plot2 <- ggplot(data.subset, aes(xData.subset, yData.subset, 
                                 color=categoricaldData.subset)) + geom_line()

那里categoricalData.subset有3个等级。

但是,两组中的特定级别最终将具有不同的颜色,这使得更难于一起读取图形。

我是否需要在数据框中创建颜色矢量?还是有另一种方法可以将特定的颜色分配给类别?

Answers:


186

对于像OP中的确切示例这样的简单情况,我同意Thierry的回答是最好的。但是,我认为有必要指出另一种方法,当您试图跨多个数据帧维护一致的配色方案时,该方法变得更加容易,而通过子集单个大数据帧无法获得所有这些数据。如果要从多个单独的文件中提取多个数据帧中的因子级别,并且并非所有因子级别都出现在每个文件中,则管理它们会变得很繁琐。

解决此问题的一种方法是创建自定义手动色标,如下所示:

#Some test data
dat <- data.frame(x=runif(10),y=runif(10),
        grp = rep(LETTERS[1:5],each = 2),stringsAsFactors = TRUE)

#Create a custom color scale
library(RColorBrewer)
myColors <- brewer.pal(5,"Set1")
names(myColors) <- levels(dat$grp)
colScale <- scale_colour_manual(name = "grp",values = myColors)

然后根据需要将色标添加到绘图上:

#One plot with all the data
p <- ggplot(dat,aes(x,y,colour = grp)) + geom_point()
p1 <- p + colScale

#A second plot with only four of the levels
p2 <- p %+% droplevels(subset(dat[4:10,])) + colScale

第一个图看起来像这样:

在此处输入图片说明

第二个情节看起来像这样:

在此处输入图片说明

这样,您就无需记住或检查每个数据框以查看它们是否具有适当的级别。


1
这将起作用,但可能过于复杂。我认为您不需要为此创建手动比例。您需要的是factor所有地块之间通用的。
Andrie

14
@Andrie-对于单个子集,是的。但是,如果您要处理很多不是通过子集一个原始数据帧而创建的所有数据集,那么我发现此策略要简单得多。
joran 2011年

2
@joran谢谢Joran。这对我有用!它创建了具有正确数量的因子的图例。我喜欢这种方法,并且获得跨不同数据集的颜色映射非常值得三行。
温图尔

3
我需要:library(“ RColorBrewer”)
PatrickT 2014年

4
工作完美!我添加了fillScale <- scale_fill_manual(name = "grp",values = myColors)此功能以用于条形图。
pentandrous

42

我处于malcook他的评论中指出的情况:不幸的是,Thierry答案不适用于ggplot2 0.9.3.1版。

png("figure_%d.png")
set.seed(2014)
library(ggplot2)
dataset <- data.frame(category = rep(LETTERS[1:5], 100),
    x = rnorm(500, mean = rep(1:5, 100)),
    y = rnorm(500, mean = rep(1:5, 100)))
dataset$fCategory <- factor(dataset$category)
subdata <- subset(dataset, category %in% c("A", "D", "E"))

ggplot(dataset, aes(x = x, y = y, colour = fCategory)) + geom_point()
ggplot(subdata, aes(x = x, y = y, colour = fCategory)) + geom_point()

这是第一个图:

ggplot AE,混合色

第二个数字:

ggplot ADE,混合色

如我们所见,颜色不是固定不变的,例如E从品红色变为蓝光。

正如malcook其评论中hadley其评论中所建议的那样,使用的代码limits可以正常工作:

ggplot(subdata, aes(x = x, y = y, colour = fCategory)) +       
    geom_point() + 
    scale_colour_discrete(drop=TRUE,
        limits = levels(dataset$fCategory))

给出下图,这是正确的:

正确的ggplot

这是来自的输出sessionInfo()

R version 3.0.2 (2013-09-25)
Platform: x86_64-pc-linux-gnu (64-bit)

locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
 [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
 [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
 [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                 
 [9] LC_ADDRESS=C               LC_TELEPHONE=C            
[11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       

attached base packages:
[1] methods   stats     graphics  grDevices utils     datasets  base     

other attached packages:
[1] ggplot2_0.9.3.1

loaded via a namespace (and not attached):
 [1] colorspace_1.2-4   dichromat_2.0-0    digest_0.6.4       grid_3.0.2        
 [5] gtable_0.1.2       labeling_0.2       MASS_7.3-29        munsell_0.4.2     
 [9] plyr_1.8           proto_0.3-10       RColorBrewer_1.0-5 reshape2_1.2.2    
[13] scales_0.2.3       stringr_0.6.2 

3
您应该将其发布为新问题,引用此问题并说明为什么此处的解决方案不起作用。
Brian Diggs 2014年

在这里提出类似的问题,但我想指出,可接受的答案很好用。
tonytonov'3

1
所以我知道这很旧,但是我想知道是否有一种方法可以在图例中没有多余的颜色的情况下进行此操作。
goryh

20

最简单的解决方案是将分类变量转换为子集之前的因子。底线是,您需要在所有子集中具有完全相同水平的因子变量。

library(ggplot2)
dataset <- data.frame(category = rep(LETTERS[1:5], 100), 
    x = rnorm(500, mean = rep(1:5, 100)), y = rnorm(500, mean = rep(1:5, 100)))
dataset$fCategory <- factor(dataset$category)
subdata <- subset(dataset, category %in% c("A", "D", "E"))

带字符变量

ggplot(dataset, aes(x = x, y = y, colour = category)) + geom_point()
ggplot(subdata, aes(x = x, y = y, colour = category)) + geom_point()

带有因子变量

ggplot(dataset, aes(x = x, y = y, colour = fCategory)) + geom_point()
ggplot(subdata, aes(x = x, y = y, colour = fCategory)) + geom_point()

11
最简单的方法是使用限制
-hadley

1
在这种情况下能否提供一个例子哈德利?我不确定如何使用限制因素。
蒂埃里(Thierry)

@Thierry谢谢。我很高兴在第一篇文章中得到回复。还要感谢Thierry或在我的帖子中添加可复制的代码...我的分类变量是正确的类型-因素。另一个问题是我希望图例不显示未使用的因素。构建图例时,R会忽略未使用的字符变量。但是,未使用的因素仍然存在。如果我使用以下命令删除它们:subdata $ category <-factor(subdata $ category)[drop = TRUE],则图例具有正确数量的因数,但会丢失映射。
温图尔

11
@Thierry-在我手中,使用ggplot2_0.9.3.1,该方法不再起作用了?在两个图中,分配给fCategory的颜色是不同的。不过,令人高兴的是,@wintour,我计算过,@hadley更是建议+ scale_colour_discrete(drop=TRUE,limits = levels(dataset$fCategory))保留色|因素的关联,但是,它的工作原理,除了在我的手中,滴= TRUE被尊重(我希望它从去除水平传奇)。德拉特...还是我?
马尔科克

1
@malcook,而不是drop = TRUE,您需要通过“ breaks”指定要保留的级别:github.com/hadley/ggplot2/issues/1433
Eric,

17

这是一篇旧文章,但我一直在寻找相同问题的答案,

为什么不尝试这样的事情:

scale_color_manual(values = c("foo" = "#999999", "bar" = "#E69F00"))

如果您具有绝对值,那么我看不出为什么它不起作用的原因。


3
这实际上是Joran的答案,但myColors <- brewer.pal(5,"Set1"); names(myColors) <- levels(dat$grp)用于避免手动编写级别。
Axeman

但是,乔兰(Joran)的答案并未对颜色的值进行硬编码。在某些情况下,您需要给定因子的特定颜色值。
勒内·尼芬格(RenéNyffenegger)

在某些情况下,尽管我遇到了“硬编码”的缺点,但我认为抽象开发人员/编码人员添加的层过多会使他们的工作难以访问,反而更多。在这种情况下,意图是100%明确的。另外,很容易想到如何制作实用程序函数,该函数在此示例中进行扩展,该函数返回特定颜色的命名矢量。
Matt Barstead

16

基于由joran我非常有用的答案是能够想出这个解决方案稳定的色标为布尔因子(TRUEFALSE)。

boolColors <- as.character(c("TRUE"="#5aae61", "FALSE"="#7b3294"))
boolScale <- scale_colour_manual(name="myboolean", values=boolColors)

ggplot(myDataFrame, aes(date, duration)) + 
  geom_point(aes(colour = myboolean)) +
  boolScale

由于ColorBrewer对二进制色标不是很有帮助,因此需要手动定义两种所需的颜色。

mybooleanmyDataFrame保存TRUE / FALSE因子的列的名称。dateduration要被映射到x上的列名和Y轴在这个例子中的情节。


另一种方法是将“ as.character()”应用于列。这将使它成为一个与scale _ * _ manual一起使用的字符串列
Sahir Moosvi,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.