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")
![重现问题](https://istack.dev59.com/nM6Sk.webp)
有几个问题需要解决:
- 从数据中我们可以得知,温度(56-81)的值比风速(5.7-20.1)的值要大得多。那么为什么上面一条线(温度的值)标记为“风”?
- 我们明确指定了红色和蓝色,但是图表中显示的是粉色/青色。为什么会这样呢?
当颜色在 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](https://istack.dev59.com/eXDHU.webp)
供参考,这是我运行原始代码时获得的结果:
![plot](https://istack.dev59.com/hCQvQ.webp)
图中显示的颜色遵循ggplot默认模板的4个值,而不是任何组合的黑/蓝/红/粉色。
此外,初始颜色值为(按顺序)c("black", "blue", "red", "pink")
,但字母顺序应该是c("black", "blue", "pink", "red")
。标签映射到这个字母顺序,这就是为什么紫色线条("轻度瘦削"根据图例)实际上是"正常范围(下限)"的线条的原因。
scale_color_identity
而不是scale_color_discrete
,并加上guide="legend"
。 - MrFlick