我有以下问题:
\n\n我有这个代码:
\n\noly12 <- VGAMdata::oly12\nggplot(oly12, aes(y = Weight, x = Height)\n) + \ngeom_hex(\n) +\nfacet_wrap("Sex", scales = "free"\n) + \ngeom_line(aes(y = 29.99*Height^2, color = "black")\n) +\ngeom_line(aes(y = 24.99*Height^2, color = "blue")\n) +\ngeom_line(aes(y = 18.50*Height^2, color = "red")\n) +\ngeom_line(aes(y = 17.00*Height^2, color = "pink")\n) +\nscale_color_discrete(name = "BMI limits", labels = c("Pre\xe2\x88\x92obese (upper \nbound)", "Normal range (upper bound)", "Normal range (lower bound)", "Mild \nthinness (lower bound)")\n) + \ntheme(legend.position="bottom", legend.direction="vertical"\n)\nRun Code Online (Sandbox Code Playgroud)\n\n我希望所有的线条都是黑色的,但是当我在代码中更改它时,所有的线条都是粉红色的,图例消失了。
\n\n我不知道如何添加图片,它不起作用,所以很抱歉,但 R 中提供了数据。
\n\n我究竟做错了什么?
\n\n谢谢
\nMrFlick 的评论已经为您提供了解决方案,因此这里尝试解释问题出在哪里。
TL;DR 解释
该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
Run Code Online (Sandbox Code Playgroud)
阴谋:
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")
Run Code Online (Sandbox Code Playgroud)
我想到了几个问题:
当在内部 指定颜色时aes(),默认情况下它被解释为变量值,而不是颜色(scale_XX_identity覆盖它)。color = "xyz"如果我用/替换上面的内容color = "abc",除了图例标签之外,图表看起来将完全相同。
本质上,ggplot 理解的代码是“线条颜色在第一个中采用变量值“红色”,在第二个中采用变量值“蓝色”;按字母顺序geom_line将“红色”和“蓝色”映射到默认调色板。如果向量提供了标签,它被映射到按字母顺序排序的向量 c("blue", "red")"
所以我们有:
|Variable |Assigned.color.value |Mapped.color.value |Mapped.label |
|:--------|:--------------------|:------------------|:------------|
|Temp |blue |pink |wind |
|Wind |red |cyan |temperature |
Run Code Online (Sandbox Code Playgroud)
(旁注:如果有两个值,则默认调色板转换为粉青色;如果有三个值,则默认调色板转换为红绿蓝;如果有四个值,则默认调色板转换为红绿蓝紫色,等等。请参阅此问题以了解有关如何使用的更多详细信息这就会发生。)
如果这还不够令人困惑,那么如果您将两种颜色更改为相同的值,就会发生这种情况(同样,该值是什么并不重要......可以是“黑色”,“白色”,“紫色”,或任何其他字符串):
|Variable |Assigned.color.value |Mapped.color.value |Mapped.label |
|:--------|:--------------------|:------------------|:------------|
|Temp |black |pink |wind |
|Wind |black |pink |wind |
Run Code Online (Sandbox Code Playgroud)
由于只给出了一个值,因此线条呈现默认调色板中的第一种颜色,并且仅将标签向量中的第一个值映射到它。因此,你的情节线条都变成了粉红色,除了第一行传说之外的所有线条都消失了。
替代解决方案
一般来说,如果我需要使用多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")
Run Code Online (Sandbox Code Playgroud)
这样做的好处是可以将所有可移动部分保留在一个地方(内部scale_XX_manual()),这样如果我以后需要更新颜色,我只需要查看那一行。对值使用命名向量还可以确保颜色和标签始终正确地相互映射。
在这种情况下,如果我想将所有线条颜色更改为黑色,我只需使用values = c("1: wind" = "black", "2: temp" = "black")即可。
作为参考,这是我运行原始代码时得到的结果:
图中显示的颜色遵循 ggplot 4 个值的默认模板,而不是黑色/蓝色/红色/粉色的任意组合。
此外,初始颜色值是(按规定的顺序)c("black", "blue", "red", "pink"),但字母顺序应该是c("black", "blue", "pink", "red")。标签映射到此字母顺序,这就是为什么紫色线(根据图例的“轻度薄度”)实际上是“正常范围(下限)”的线。