如何在ggplot2中更改线条颜色而不使图例消失?

4

我有以下问题:

我有这段代码:

oly12 <- VGAMdata::oly12
ggplot(oly12, aes(y = Weight, x = Height)
) + 
geom_hex(
) +
facet_wrap("Sex", scales = "free"
) + 
geom_line(aes(y = 29.99*Height^2, color = "black")
) +
geom_line(aes(y = 24.99*Height^2, color = "blue")
) +
geom_line(aes(y = 18.50*Height^2, color = "red")
) +
geom_line(aes(y = 17.00*Height^2, color = "pink")
) +
scale_color_discrete(name = "BMI limits", labels = c("Pre−obese (upper 
bound)", "Normal range (upper bound)", "Normal range (lower bound)", "Mild 
thinness (lower bound)")
) + 
theme(legend.position="bottom", legend.direction="vertical"
)

我希望所有的线都是黑色的,但当我在代码中更改时,所有的线都变成了粉色,图例消失了。
我不知道如何添加图片,它不能正常工作,所以很抱歉,但数据在R中可用。
我做错了什么?
谢谢。

3
看起来你应该使用scale_color_identity而不是scale_color_discrete,并加上guide="legend" - MrFlick
1个回答

6

MrFlick的评论已经给出了解决方案,所以这里尝试解释一下出现问题的原因。

简短的解释

color = "some color" 部分在 aes() 内部,但 scale_color_discrete() 没有准备好正确处理它。

详细的解释

让我们使用一个基本数据集来进行说明,因为并不是每个人都有 VGAMdata 包:

df <- subset(airquality, Month == 5)[, c("Day", "Wind", "Temp")]

> head(df)
  Day Wind Temp
1   1  7.4   67
2   2  8.0   72
3   3 12.6   74
4   4 11.5   62
5   5 14.3   56
6   6 14.9   66

> summary(df)
      Day            Wind            Temp      
 Min.   : 1.0   Min.   : 5.70   Min.   :56.00  
 1st Qu.: 8.5   1st Qu.: 8.90   1st Qu.:60.00  
 Median :16.0   Median :11.50   Median :66.00  
 Mean   :16.0   Mean   :11.62   Mean   :65.55  
 3rd Qu.:23.5   3rd Qu.:14.05   3rd Qu.:69.00  
 Max.   :31.0   Max.   :20.10   Max.   :81.00  

故事梗概:

ggplot(df,
       aes(x = Day)) +
  geom_line(aes(y = Wind, color = "red")) +
  geom_line(aes(y = Temp, color = "blue")) +
  scale_color_discrete(name = "Variables",
                       labels = c("wind", "temperature")) +
  theme(legend.position = "bottom", 
        legend.direction = "vertical")

重现问题

有几个问题需要解决:

  1. 从数据中我们可以得知,温度(56-81)的值比风速(5.7-20.1)的值要大得多。那么为什么上面一条线(温度的值)标记为“风”?
  2. 我们明确指定了红色和蓝色,但是图表中显示的是粉色/青色。为什么会这样呢?

当颜色在 aes() 内部被指定时,默认情况下它会被解释为变量值,而不是颜色(scale_XX_identity 可以覆盖这个默认设置)。如果我将上述代码替换为 color = "xyz" / color = "abc",则图表看起来完全相同,除了图例标签。

基本上,ggplot 理解这段代码的意思是:“第一个 geom_line 的线条颜色采用变量值 'red',第二个 geom_line 的线条颜色采用变量值 'blue';按字母顺序将“red”和“blue”映射到默认的调色板中。如果提供了标签向量,则将其映射到按字母顺序排序的 c("blue", "red") 向量中。”

因此我们有:

|Variable |Assigned.color.value |Mapped.color.value |Mapped.label |
|:--------|:--------------------|:------------------|:------------|
|Temp     |blue                 |pink               |wind         |
|Wind     |red                  |cyan               |temperature  |

(附注:默认调色板在有两个值时为粉青色,有三个值时为红绿蓝色,有四个值时为红绿蓝紫色等等。详见这个问题了解更多细节。)同时,如果你将两种颜色改为相同的值,会发生以下情况(同样,不管该值是什么,可能是“黑色”,“白色”,“紫色”或其他任何字符字符串):
|Variable |Assigned.color.value |Mapped.color.value |Mapped.label |
|:--------|:--------------------|:------------------|:------------|
|Temp     |black                |pink               |wind         |
|Wind     |black                |pink               |wind         |

由于只提供了一个数值,所以这些线采用默认调色板中的第一种颜色,并且标签向量中仅有的第一个值被映射到它上面。因此,您绘制的所有线都变成了粉色,并且除了图例中的第一条线之外,其余的都消失了。

替代方案

通常情况下,如果我需要使用多个 geom_line() 线并为每个线分配不同的颜色(而不是将原始数据转换为长格式),我更喜欢在 aes() 内部使用其预期的标签来定义每条线的颜色,并手动指定相应的颜色使用 scale_XX_manual()

ggplot(df,
       aes(x = Day)) +
  geom_line(aes(y = Wind, color = "1: wind")) +
  geom_line(aes(y = Temp, color = "2: temp")) +
  scale_color_manual(name = "Variables",
                     values = c("1: wind" = "red", "2: temp" = "blue")) +
  theme(legend.position = "bottom", 
        legend.direction = "vertical")

这样做的好处是将所有可移动部分放在一个地方(scale_XX_manual()内部),所以如果我需要稍后更新颜色,我只需要查看那一行即可。使用命名向量值也确保颜色和标签始终正确映射到一起。

在这种情况下,如果我想将所有线条颜色更改为黑色,我只需使用values = c("1: 风" = "black", "2: 温度" = "black")

plot2

供参考,这是我运行原始代码时获得的结果:

plot

图中显示的颜色遵循ggplot默认模板的4个值,而不是任何组合的黑/蓝/红/粉色。

此外,初始颜色值为(按顺序)c("black", "blue", "red", "pink"),但字母顺序应该是c("black", "blue", "pink", "red")。标签映射到这个字母顺序,这就是为什么紫色线条("轻度瘦削"根据图例)实际上是"正常范围(下限)"的线条的原因。


非常感谢,现在我明白了! :) - Grunka

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接