自定义ggplot图例

时间:2018-08-14 10:49:26

标签: r ggplot2

假设我有一些数据,并且想使用ggplot绘制预测和95%的预测间隔。以下代码可以正常工作并给出可接受的图例。

ExampleData = data.frame(t = 1:10, f = rep(1,10), Lower = rep(0.5, 10), Upper = rep(1.5, 10))
library (ggplot2)
ggplot(data = ExampleData)+
  geom_point(aes(x=t, y =f, colour = "Forecasts"))+
  geom_point(aes(x=t, y =Lower), shape=95)+
  geom_segment(aes(x=t, y = Lower, xend=t, yend = f))+
  geom_point(aes(x=t, y =Upper), shape=95)+
  geom_segment(aes(x=t, y = f, xend=t, yend = Upper))+
  geom_vline(aes(xintercept = 11, colour = "95% PI"))+
  scale_colour_manual(values = c("95% PI" = "black","Forecasts" = "red"),
                      guide = guide_legend(override.aes = list(
                        linetype = c('solid','blank'),
                        shape = c(NA,16))))+
  scale_x_continuous(name="Time", limits=c(1, 10), breaks = c(0,5,10))+
  labs(title="Example")+
  labs(y = "Forecasts")+
  theme_bw()

rplot of the example

我也想添加一条水平线,例如y = 0.75。但是,图例似乎无法容纳水平和垂直线。有没有一种方法可以使用ggplot做到这一点?还包括较短的水平线呢?例如,上下点由短水平线表示。

2 个答案:

答案 0 :(得分:3)

考虑到OP的评论进行更新:

如果定义了美学colorfillgroup,...,则元素会自动添加到图例中。因此,类似geom_line(aes(color = 'foo'))的东西会产生一个名为 foo 的图例元素,但是geom_line(color = 'black')不会。

library (ggplot2)
ExampleData = data.frame(t = 1:10, f = 1, Lower = 0.5, Upper = 1.5)

g <- ggplot(data = ExampleData, aes(x = t))

g <- g + geom_point(aes(y = f, color = "95% PI"), size = 0)
g <- g + geom_errorbar(aes(ymin = Lower, ymax = Upper, color = "95% PI"))
g <- g + geom_point(aes(y = f), color = "red")
g <- g + geom_line(aes(y = 0.75, color = "Threshold"))

g <- g + scale_colour_manual(values = c("95% PI"    = "black",
                                        "Threshold" = "green"),
                             guide = guide_legend(override.aes = list(
                               linetype = c('blank', 'solid'),
                               shape    = c('|',      NA),
                               size     = c(5,        0.5))))

g <- g + theme_bw()
g <- g + scale_x_continuous(name="Time", breaks = c(0, 5, 10))
g <- g + labs(title = "Example")
g <- g + labs(y = "Forecasts")

print(g)

这将产生如下输出: Results of the RPlot above

要在图例中获得垂直线,我添加了一个不可见的geom_point(大小为0,因此,请参见下文)。请注意,color美学已经定义,因此图例将由该元素填充。要将水平线添加到固定值为 y 的图以及图例,最简单的方法是使用geom_line元素设置{{ 1}}美学。最后,要显示红点并将其从图例中排除,您必须设置color的美感。

color

关于图例,要具有垂直条而不是水平条(默认),可以使用形状g <- g + geom_point(aes(y = f, color = "95% PI"), size = 0) g <- g + geom_errorbar(aes(ymin = Lower, ymax = Upper, color = "95% PI")) g <- g + geom_line(aes(y = 0.75, color = "Threshold")) g <- g + geom_point(aes(y = f), color = "red") 。默认情况下,这是一个很小的形状(至少在我的计算机上),因此您可能必须稍微增加它的大小。您可以通过玩指南来做到这一点。请注意,|geom_errorbar并不具有geom_segment属性。要使用形状而不是线条,您需要先添加不可见的shape

geom_point

上一个答案:

假设您想在图例中使用所有点,垂直线段,水平线段和水平线,这是我的建议:

g <- g + scale_colour_manual(values = c("95% PI"    = "black",
                                        "Threshold" = "green"),
                             guide = guide_legend(override.aes = list(
                               linetype = c('blank', 'solid'),
                               shape    = c('|',      NA),
                               size     = c(5,        0.5))))

Rplot of the example

ExampleData = data.frame(t = 1:10, f = rep(1,10), Lower = rep(0.5, 10), Upper = rep(1.5, 10))
library (ggplot2)

tipw <- 0.2
g <- ggplot(data = ExampleData)

g <- g + geom_segment(aes(x = t, y = Lower, xend = t, yend = Upper, color = "95% PI"))
g <- g + geom_segment(aes(x = t - tipw / 2, y = Lower, xend = t + tipw / 2, yend = Lower, color = "Minimum"))
g <- g + geom_segment(aes(x = t - tipw / 2, y = Upper, xend = t + tipw / 2, yend = Upper, color = "Maximum"))
g <- g + geom_point(aes(x = t, y = f, color = "Forecasts"))
g <- g + geom_line(aes(x = t, y = 0.75, color = "Some value"))

g <- g + scale_x_continuous(name="Time", limits=c(1 - tipw/2, 10 + tipw/2), breaks = c(0, 5, 10))
g <- g + labs(title = "Example")
g <- g + labs(y = "Forecasts")

g <- g + scale_colour_manual(values = c("95% PI"     = "black",
                                        "Forecasts"  = "red",
                                        "Minimum"    = "orange",
                                        "Maximum"    = "green",
                                        "Some value" = "light blue"),
                             guide = guide_legend(override.aes = list(
                                     linetype = c('solid', 'blank', 'solid', 'solid', 'solid'),
                                     shape    = c(NA,      16,      NA,      NA,      NA))))
g <- g + theme_bw()

print(g)

使用数据创建图。 tipw <- 0.2 g <- ggplot(data = ExampleData) 变量是笔尖的宽度(使用与 x轴相同的单位)。见下文。

tipw

添加线,线段和点。元素将按照您编写它们的顺序堆叠。因此,这里将首先绘制技巧中的短水平条,然后绘制垂直条,然后绘制条顶部的点,然后再绘制其余部分顶部的任意水平线。

请记住,您可以在ggplot美学方面做一些逻辑。此处将短水平条定义为从g <- g + geom_segment(aes(x = t, y = Lower, xend = t, yend = Upper, color = "95% PI")) g <- g + geom_segment(aes(x = t - tipw / 2, y = Lower, xend = t + tipw / 2, yend = Lower, color = "Minimum")) g <- g + geom_segment(aes(x = t - tipw / 2, y = Upper, xend = t + tipw / 2, yend = Upper, color = "Maximum")) g <- g + geom_point(aes(x = t, y = f, color = "Forecasts")) g <- g + geom_line(aes(x = t, y = 0.75, color = "Some value")) 开始到x = t - tipw / 2结束的段。可以将长水平条手动定义为x = t + tipw / 2。之所以可行,是因为您始终可以将长度为1的向量用于美观,并且该值将用于所有点({y = 0.75的结果与aes(x = t, y = 0.75)相同)。

aes(x = t, y = rep(0.75, length(t)))

您必须包括水平线段的 xstart xend 才能绘制它们。这就是将限制扩展g <- g + scale_x_continuous(name = "Time", limits=c(1 - tipw/2, 10 + tipw/2), breaks = c(0, 5, 10)) 的原因。否则,最左边和最右边的水平条将不可见,并会发出警告。

tipw/2

答案 1 :(得分:0)

我更新了@Slagt答案,将点添加到图例中:

library (ggplot2)
ExampleData = data.frame(t = 1:10, f = 1, Lower = 0.5, Upper = 1.5)

ggplot(data = ExampleData, aes(x = t)) + 
  geom_errorbar(aes(ymin = Lower, ymax = Upper, color = "95% PI"), width = 0) + 
  geom_point(aes(y = f, color = "Forecasts")) + 
  geom_line(aes(y = 0.75, color = "Threshold")) + 
  scale_colour_manual(values = c("95% PI"    = "black",
                                 "Forecasts"  = "red",
                                 "Threshold" = "green"),
                      guide = guide_legend(override.aes = list(
                        linetype = c("blank", "blank", "solid"),
                        shape    = c(124, 16, NA),
                        size     = c(5, 1.5, 0.5)))) + 
  theme_bw() + 
  scale_x_continuous(name="Time", breaks = c(0, 5, 10)) + 
  labs(title = "Example", y = "Forecasts")

enter image description here

垂直线的特殊形状非常不错。但是,也应该可以在图例中旋转线。可以通过修改GeomErrorbar$draw_keyGeomLine$draw_key函数来完成此操作:

library(grid)
GeomErrorbar$draw_key <- function(data, params, size) 
{
  segmentsGrob(x0 = 0.5, y0 = 0, x1 = 0.5, y1 = 1, 
               gp = gpar(col = alpha(data$colour, data$alpha), 
                         lwd = data$size * .pt, 
                         lty = ifelse(data$colour == "green", 
                                      0, data$linetype), 
                         lineend = "butt"))
}
GeomLine$draw_key <- function(data, params, size) 
{
  segmentsGrob(x0 = 0, y0 = 0.5, x1 = 1, y1 = .5, 
               gp = gpar(col = alpha(data$colour, data$alpha), 
                         lwd = data$size * .pt, 
                         lty = ifelse(data$colour == "black", 
                                      0, data$linetype), 
                         lineend = "butt"))
}

对于geom_errorbar,我将图例行设置为垂直,对于geom_line,将图例线设置为水平。为了防止交叉效果,我基于颜色为lty自变量添加了条件。

然后简单地创建情节:

ggplot(data = ExampleData, aes(x = t)) + 
  geom_errorbar(aes(ymin = Lower, ymax = Upper, color = "95% PI"), 
                width = 0) + 
  geom_point(aes(y = f, color = "Forecasts")) + 
  geom_line(aes(y = 0.75, color = "Threshold")) + 
  scale_colour_manual(values = c("95% PI"    = "black",
                                 "Forecasts"  = "red",
                                 "Threshold" = "green"),
                      guide = guide_legend(override.aes = list(
                        linetype = c("solid", "blank", "solid"),
                        shape = c(NA, 16, NA)))) + 
  theme_bw() + 
  scale_x_continuous(name="Time", breaks = c(0, 5, 10)) + 
  labs(title = "Example") + labs(y = "Forecasts")

enter image description here