为 ggplot2 线图添加图例

Add legend to ggplot2 line plot

提问人:pacomet 提问时间:4/27/2012 最后编辑:tjebopacomet 更新时间:11/20/2022 访问量:396724

问:

我有一个关于 ggplot2 中的图例的问题。我设法在同一张图中绘制了三条线,并想添加一个使用三种颜色的图例。这是使用的代码

library(ggplot2)

## edit from original post - removed lines that downloaded data from broken link. Data snippet now below.
## Here a subset as used by [Brian Diggs in their answer](https://stackoverflow.com/a/10355844/7941188)
datos <- structure(list(fecha = structure(c(1317452400, 1317538800, 1317625200, 1317711600, 1317798000, 1317884400, 1317970800, 1318057200, 1318143600, 1318230000, 1318316400, 1318402800, 1318489200, 1318575600, 1318662000, 1318748400, 1318834800, 1318921200, 1319007600, 1319094000), class = c("POSIXct", "POSIXt"), tzone = ""), TempMax = c(26.58, 27.78, 27.9, 27.44, 30.9, 30.44, 27.57, 25.71, 25.98, 26.84, 33.58, 30.7, 31.3, 27.18, 26.58, 26.18, 25.19, 24.19, 27.65, 23.92), TempMedia = c(22.88, 22.87, 22.41, 21.63, 22.43, 22.29, 21.89, 20.52, 19.71, 20.73, 23.51, 23.13, 22.95, 21.95, 21.91, 20.72, 20.45, 19.42, 19.97, 19.61), TempMin = c(
  19.34, 19.14, 18.34, 17.49, 16.75, 16.75, 16.88, 16.82, 14.82, 16.01, 16.88, 17.55, 16.75, 17.22, 19.01,
  16.95, 17.55, 15.21, 14.22, 16.42
)), .Names = c(
  "fecha", "TempMax",
  "TempMedia", "TempMin"
), row.names = c(NA, 20L), class = "data.frame")

ggplot(data = datos, aes(x = fecha, y = TempMax, colour = "1")) +
  geom_line(colour = "red") +
  geom_line(aes(x = fecha, y = TempMedia, colour = "2"), colour = "green") +
  geom_line(aes(x = fecha, y = TempMin, colour = "2"), colour = "blue") +
  scale_y_continuous(limits = c(-10, 40)) +
  scale_colour_manual(values = c("red", "green", "blue")) +
  labs(title = "TITULO", x = NULL, y = "Temperatura (C)") 

我想添加一个图例,其中包含使用的三种颜色和变量的名称(TempMax、TempMedia 和 TempMin)。我试过了,但找不到确切的方法。scale_colour_manual

GGPLOT2 图例 R-FAQ

评论

2赞 Etienne Low-Décarie 4/27/2012
我仍然很好奇传说是否可以与情节的不同元素(例如不同的geom_line)联系起来。
0赞 Tyler Rinker 4/27/2012
如果您只有 3 行,我建议您查看 dirrectlabels 包。(链接)
0赞 pacomet 4/27/2012
@TylerRinker我以前曾将其用于其他目的,但现在 csgillespie 的答案更适合我
0赞 joran 4/27/2012
@EtienneLow-Décarie 你可以,但一般来说,只有当他们使用不同的美学时。例如,将一组线映射到颜色,将另一组线映射到线型。在这种情况下,通常也会将单独的数据传递到每个几何图形。
0赞 tjebo 11/20/2022
相关 stackoverflow.com/questions/3777174/...

答:

93赞 csgillespie 4/27/2012 #1

我倾向于发现,如果我在多个几何图形中指定单个颜色,我就做错了。以下是我绘制数据的方式:

library(ggplot2)
library(tidyr)

dd_tidyr <- pivot_longer(datos, cols = -fecha, names_to = "Temperature")

剩下的就是一个简单的 ggplot 命令:

ggplot(dd_tidyr) +
  geom_line(aes(x = fecha, y = value, colour = Temperature)) +
  scale_colour_manual(values = c("red", "green", "blue"))

还有其他方法可以重塑数据。一种被取代的方法是使用现已停用的 {reshape2} 包。

library(reshape2)
dd = melt(datos, id=c("fecha"))

评论

107赞 Etienne Low-Décarie 4/27/2012
我仍然很好奇如何添加与单独添加元素(如geom_line)相关的图例,尽管这是问题的最初目的。
4赞 teunbrand 5/21/2021
因为这个答案被引用了很多,而且因为 reshape2 已经停用,所以展示一种重塑数据的方法可能会很好。tidyr::pivot_longer()
249赞 Brian Diggs 4/28/2012 #2

由于@Etienne被问到如何在不融化数据的情况下做到这一点(这通常是首选方法,但我认识到在某些情况下可能是不可能的),因此我提出了以下替代方案。

从原始数据的子集开始:

datos <-
structure(list(fecha = structure(c(1317452400, 1317538800, 1317625200, 
1317711600, 1317798000, 1317884400, 1317970800, 1318057200, 1318143600, 
1318230000, 1318316400, 1318402800, 1318489200, 1318575600, 1318662000, 
1318748400, 1318834800, 1318921200, 1319007600, 1319094000), class = c("POSIXct", 
"POSIXt"), tzone = ""), TempMax = c(26.58, 27.78, 27.9, 27.44, 
30.9, 30.44, 27.57, 25.71, 25.98, 26.84, 33.58, 30.7, 31.3, 27.18, 
26.58, 26.18, 25.19, 24.19, 27.65, 23.92), TempMedia = c(22.88, 
22.87, 22.41, 21.63, 22.43, 22.29, 21.89, 20.52, 19.71, 20.73, 
23.51, 23.13, 22.95, 21.95, 21.91, 20.72, 20.45, 19.42, 19.97, 
19.61), TempMin = c(19.34, 19.14, 18.34, 17.49, 16.75, 16.75, 
16.88, 16.82, 14.82, 16.01, 16.88, 17.55, 16.75, 17.22, 19.01, 
16.95, 17.55, 15.21, 14.22, 16.42)), .Names = c("fecha", "TempMax", 
"TempMedia", "TempMin"), row.names = c(NA, 20L), class = "data.frame")

您可以通过以下方式获得所需的效果(这也清理了原始绘图代码):

ggplot(data = datos, aes(x = fecha)) +
  geom_line(aes(y = TempMax, colour = "TempMax")) +
  geom_line(aes(y = TempMedia, colour = "TempMedia")) +
  geom_line(aes(y = TempMin, colour = "TempMin")) +
  scale_colour_manual("", 
                      breaks = c("TempMax", "TempMedia", "TempMin"),
                      values = c("red", "green", "blue")) +
  xlab(" ") +
  scale_y_continuous("Temperatura (C)", limits = c(-10,40)) + 
  labs(title="TITULO")

这个想法是通过将美学映射到一个恒定的字符串来赋予每条线一种颜色。选择要在图例中显示的字符串是最简单的。在这种情况下,它与正在绘制的变量的名称相同这一事实并不重要;它可以是任何一组字符串。这在通话中非常重要;您正在创建到此“变量”的映射。colouryaes

scale_colour_manual现在可以将这些字符串映射到适当的颜色。结果是enter image description here

在某些情况下,需要通过命名手动刻度中的值来明确级别和颜色之间的映射(感谢 @DaveRGP 指出这一点):

ggplot(data = datos, aes(x = fecha)) +
  geom_line(aes(y = TempMax, colour = "TempMax")) +
  geom_line(aes(y = TempMedia, colour = "TempMedia")) +
  geom_line(aes(y = TempMin, colour = "TempMin")) +
  scale_colour_manual("", 
                      values = c("TempMedia"="green", "TempMax"="red", 
                                 "TempMin"="blue")) +
  xlab(" ") +
  scale_y_continuous("Temperatura (C)", limits = c(-10,40)) + 
  labs(title="TITULO")

(给出与以前相同的数字)。使用命名值时,可以使用中断符在图例中设置顺序,并且可以在值中使用任何顺序。

ggplot(data = datos, aes(x = fecha)) +
  geom_line(aes(y = TempMax, colour = "TempMax")) +
  geom_line(aes(y = TempMedia, colour = "TempMedia")) +
  geom_line(aes(y = TempMin, colour = "TempMin")) +
  scale_colour_manual("", 
                      breaks = c("TempMedia", "TempMax", "TempMin"),
                      values = c("TempMedia"="green", "TempMax"="red", 
                                 "TempMin"="blue")) +
  xlab(" ") +
  scale_y_continuous("Temperatura (C)", limits = c(-10,40)) + 
  labs(title="TITULO")

评论

2赞 DaveRGP 1/20/2015
我喜欢这个解决方案,但我认为可能存在局限性。“breaks”和“values”变量的映射之间是否存在字母排序问题?TempM{a]x、TempM{e}dia 和 TempM{i}n 排序整齐,但当我将其调整为我的变量名称时,颜色似乎按字母顺序与“中断”匹配,而不是按顺序输入。是否可以澄清/完善上述内容以反映/解决这个问题?
4赞 DaveRGP 2/3/2015
我已经设法找到了解决我之前购买的问题的方法:颜色排序。使用将 TempMax、TempMedia 和 TempMin 指定为颜色参数的形式,如上面的答案所示。scale_colour_manual("", values = c("TempMax" = "red", "TempMedia" = "green", "TempMin" = "blue"))
0赞 Alessandro Jacopson 6/16/2015
@DaveRGP 可以算是ggplot的bug吗?
1赞 Brian Diggs 1/31/2017
@StellaBiderman谢谢。很高兴知道这个答案在 5 年后(几乎)仍然有用。
1赞 Stella Biderman 1/31/2017
@BrianDiggs 你不会碰巧知道如何让这个节目成为刻度上的一个点而不是一条线,对吗?
2赞 Justyna 5/3/2018 #3

我真的很喜欢 @Brian Diggs 提出的解决方案。然而,就我而言,我在循环中创建线图,而不是明确给出它们,因为我不知道先验地知道我将有多少个图。当我尝试调整@Brian的代码时,我在正确处理颜色时遇到了一些问题。原来我需要修改美学功能。如果有人遇到同样的问题,这里是对我有用的代码。

我使用了与@Brian相同的数据框:

data <- structure(list(month = structure(c(1317452400, 1317538800, 1317625200, 1317711600, 
                                       1317798000, 1317884400, 1317970800, 1318057200, 
                                       1318143600, 1318230000, 1318316400, 1318402800, 
                                       1318489200, 1318575600, 1318662000, 1318748400, 
                                       1318834800, 1318921200, 1319007600, 1319094000), 
                                     class = c("POSIXct", "POSIXt"), tzone = ""),
                   TempMax = c(26.58, 27.78, 27.9, 27.44, 30.9, 30.44, 27.57, 25.71, 
                               25.98, 26.84, 33.58, 30.7, 31.3, 27.18, 26.58, 26.18, 
                               25.19, 24.19, 27.65, 23.92), 
                   TempMed = c(22.88, 22.87, 22.41, 21.63, 22.43, 22.29, 21.89, 20.52,
                                 19.71, 20.73, 23.51, 23.13, 22.95, 21.95, 21.91, 20.72, 
                                 20.45, 19.42, 19.97, 19.61), 
                   TempMin = c(19.34, 19.14, 18.34, 17.49, 16.75, 16.75, 16.88, 16.82, 
                               14.82, 16.01, 16.88, 17.55, 16.75, 17.22, 19.01, 16.95, 
                               17.55, 15.21, 14.22, 16.42)), 
              .Names = c("month", "TempMax", "TempMed", "TempMin"), 
              row.names = c(NA, 20L), class = "data.frame")  

就我而言,我是动态生成的,但我不想让事情变得不必要地复杂,所以我在这里明确地给出它们。这三行使图例的排序和颜色分配更加容易。my.colsmy.names

my.cols <- heat.colors(3, alpha=1)
my.names <- c("TempMin", "TempMed", "TempMax")
names(my.cols) <- my.names

这是情节:

p <-  ggplot(data, aes(x = month))

for (i in 1:3){
  p <- p + geom_line(aes_(y = as.name(names(data[i+1])), colour = 
colnames(data[i+1])))#as.character(my.names[i])))
}
p + scale_colour_manual("", 
                        breaks = as.character(my.names),
                        values = my.cols)
p

enter image description here

评论

5赞 Axeman 5/14/2018
在这种复杂性下,将数据重塑为预期的长格式确实变得容易得多。ggplot
4赞 Justyna 5/16/2018
与@Brian发布的原始答案相比,我认为这并没有真正增加复杂性。此外,有些人可能希望在不重塑数据的情况下做到这一点。
1赞 mac 11/10/2018
...这种方法允许通过变量实现不同的几何形状(绘图类型)
1赞 Quinten 11/19/2022 #4

另一个选项使用 .关键是在每个 .在中,您可以提及每种颜色并添加您想要的颜色。下面是一个可重现的例子:scale_color_identityaesgeom_linescale_color_identitybreakslabels

library(ggplot2)    

temp = ggplot(data = datos, aes(x = fecha)) +
  geom_line(aes(y = TempMax, colour = "red")) +
  geom_line(aes(y = TempMedia, colour = "green")) +
  geom_line(aes(y = TempMin, colour = "blue")) +
  labs(title="TITULO") +
  ylab("Temperatura (C)") + 
  xlab(" ") + 
  scale_y_continuous(limits = c(-10,40)) + 
  scale_color_identity(name = '',
                       breaks = c('red', 'green', 'blue'),
                       labels = c("TempMax", "TempMedia", "TempMin"),
                       guide = 'legend')

temp

创建于 2022-11-19,使用 reprex v2.0.2