r ggplot2 图例:如何在符号下方显示线型?

r ggplot2 legend: how to display linetype below symbol?

我正在绘制一个图形,该图形同时使用符号和线型来区分组(分别为点和 95% 置信度椭圆)。

这是一个具有类似图例的示例图:

  bplot<-ggplot(iris,aes(x=Sepal.Length,y=Sepal.Width,group=Species,shape=Species,lty=Species))+
    geom_point(size=3)+geom_smooth(method="lm",se=F,color="black")+
    theme_minimal()+theme(legend.key.size=unit(1.2,"cm"))
  bplot

问题是线型很难在图例中看到,因为它们与符号重叠。有没有办法在与符号相同的图例中显示线型(使用单个标签),但在符号下方或以两者都可读的方式显示?

您需要 guides 功能。请阅读文档以进行更多自定义。

bplot<-ggplot(iris,aes(x=Sepal.Length,y=Sepal.Width,group=Species,shape=Species,lty=Species))+
  geom_point(size=3)+geom_smooth(method="lm",se=F,color="black")+
  theme_minimal()+theme(legend.key.size=unit(1.2,"cm")) + 
  guides(
    shape = guide_legend(order = 1),
    size = guide_legend(order = 2)
  )
bplot

我认为如果按键加宽一点,图例是可读的。

library(ggplot2)

bplot <- ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width, group = Species,
                          shape = Species,lty = Species)) +
  geom_point(size = 3) +
  geom_smooth(method = "lm", se = F, color = "black") +
  theme_minimal() +
  theme(legend.key.width = unit(1.5, "cm"))

bplot

但是如果你想在每个键中将点与线分开,那么我认为你需要深入研究 ggplot grob。

library(grid)

bplot <- ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width, group = Species,
                          shape = Species,lty = Species)) +
  geom_point(size = 3) +
  geom_smooth(method = "lm", se = F, color = "black") +
  theme_minimal() +
  theme(legend.key.width = unit(1.5, "cm"),
        legend.key.height = unit(1, "cm"),
        legend.key = element_rect(colour = "grey50", size = .5))

# Get the plot grob
g = ggplotGrob(bplot)

# Get the legend
leg = g$grobs[[which(g$layout$name == "guide-box")]]

# Get the relevant keys
pos = grep("key-.-1-1", leg$grobs[[1]]$layout$name)
# pos gets the point; pos+1 gets the line

# Separate the line from the point within each key
for(i in pos) {
   leg$grobs[[1]]$grobs[[i]]$y = unit(0.6, "npc")

   leg$grobs[[1]]$grobs[[i+1]]$children[[1]]$y0 = unit(0.3, "npc")
   leg$grobs[[1]]$grobs[[i+1]]$children[[1]]$y1 = unit(0.3, "npc")
}

# Put the legend back into the plot
g$grobs[[which(g$layout$name == "guide-box")]] = leg

# Draw it
grid.newpage()
grid.draw(g)

或者,如果您想要单独的图例,请参阅@Divi 的回答

此处的其中一篇帖子给出了在 ggplot grob 中编辑特定 grob 的一个选项。它涉及通过列表中的长列表遵循路径以获取相关的 grob。有时,使用 grid 编辑功能编辑相关的 grob 会更容易(尽管可能只是略微如此)。

library(ggplot2)
library(grid)

# The plot
bplot <- ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width, group = Species,
                          shape = Species,lty = Species)) +
  geom_point(size = 3) +
  geom_smooth(method = "lm", se = F, color = "black") +
  theme_minimal() +
  theme(legend.key.width = unit(1.5, "cm"),
        legend.key.height = unit(1, "cm"),
        legend.key = element_rect(colour = "grey50", size = .5))

# Get the plot grob
g = ggplotGrob(bplot)

# Get a list of the grobs 
grid.ls(grid.force(g)) 

查看抢劫列表。我们要编辑的 grob 位于列表底部 - 名称以 "key" 开头。有三组三组 - 三组是因为图例中有三个键。在每个组中,有三个 grobs:

key-3-1-bg.4-2-4-2
key-3-1-1.4-2-4-2
key-3-1-2.4-2-4-2
    GRID.segments.819

首先是背景 - 此处不感兴趣。
第二个指的是点——我们要编辑它的垂直位置。
第三个是指包含子项的 grob - GRID.segments - 线段。我们要编辑线段的垂直位置。

editGrob()命令中,gPath列出要编辑的grob,但grep=TRUE表示可以使用正则表达式,global=TRUE表示全部匹配被影响。因此,每次编辑只有一个命令。

# Edit the 'key' grobs
# Move the point up a little
g = editGrob(grid.force(g), gPath("key-[1-9]-1-1"), grep = TRUE, global = TRUE,  
         y = unit(0.6, "npc"))

# Move the line segment down a little
g = editGrob(grid.force(g), gPath("GRID.segments"), grep = TRUE, global = TRUE,  
         y0 = unit(0.3, "npc"), y1 = unit(0.3, "npc"))

# Draw it
grid.newpage()
grid.draw(g)