34

我想从 ggplot2 创建的网格对象中删除一个layer(在这种情况下是 的结果)。geom_ribbon一旦它已经是对象的一部分,有没有办法可以将其删除?

library(ggplot2)
dat <- data.frame(x=1:3, y=1:3, ymin=0:2, ymax=2:4)
p <- ggplot(dat, aes(x=x, y=y)) + geom_ribbon(aes(ymin=ymin, ymax=ymax), alpha=0.3) 
     + geom_line()

# This has the geom_ribbon
p

# This overlays another ribbon on top
p + geom_ribbon(aes(ymin=ymin, ymax=ymax, fill=NA))

我希望这个功能允许我在不太复杂的情节之上构建更复杂的情节。我正在使用返回网格对象的函数,然后在完全组装后打印出最终图。基图有一条线,geom_ribbon周围有一个相应的误差线 ( )。更复杂的情节将有几条线,并且多个重叠的geom_ribbon对象会分散注意力。我想将它们从多行的图中删除。此外,我将能够使用构面或其他 ggplot2 功能快速创建替代版本。


编辑:接受@mnel's answer as it works。现在我需要确定如何动态访问该geom_ribbon层,这在此处的 SO 问题中被捕获。


编辑2:为了完整起见,这是我为解决这个问题而创建的函数:

remove_geom <- function(ggplot2_object, geom_type) {
  layers <- lapply(ggplot2_object$layers, function(x) if(x$geom$objname == geom_type) NULL else x)
  layers <- layers[!sapply(layers, is.null)]

  ggplot2_object$layers <- layers
  ggplot2_object
}

编辑 3:有关最新版本的 ggplot (>=2.xy),请参阅下面接受的答案

4

5 回答 5

21

如果你看

p$layers
[[1]]
mapping: ymin = ymin, ymax = ymax 
geom_ribbon: na.rm = FALSE, alpha = 0.3 
stat_identity:  
position_identity: (width = NULL, height = NULL)

[[2]]
geom_line:  
stat_identity:  
position_identity: (width = NULL, height = NULL)

您将看到要删除第一层

您可以通过将图层重新定义为列表中的第二个组件来完成此操作。

p$layer <- p$layer[2]

现在构建和绘图p

p

请注意,这p$layer[[1]] <- NULL也可以。我同意@Andrie 和@Joran 关于在某些情况下这可能有用的评论,并且不认为这一定是可靠的。 在此处输入图像描述

于 2012-11-15T22:31:51.873 回答
21

对于 ggplot2 2.2.1 版,我不得不remove_geom像这样修改提议的函数:

remove_geom <- function(ggplot2_object, geom_type) {
  # Delete layers that match the requested type.
  layers <- lapply(ggplot2_object$layers, function(x) {
    if (class(x$geom)[1] == geom_type) {
      NULL
    } else {
      x
    }
  })
  # Delete the unwanted layers.
  layers <- layers[!sapply(layers, is.null)]
  ggplot2_object$layers <- layers
  ggplot2_object
}

以下是如何使用它的示例:

library(ggplot2)

set.seed(3000)
d <- data.frame(
  x = runif(10),
  y = runif(10),
  label = sprintf("label%s", 1:10)
)

p <- ggplot(d, aes(x, y, label = label)) + geom_point() + geom_text()

让我们显示原始情节:

p

带有文本标签的绘图

现在让我们删除标签并再次显示绘图:

p <- remove_geom(p, "GeomText")
p

没有文本标签的绘图

于 2017-09-14T13:55:14.433 回答
8

由于这个问题看起来很有趣,我已经扩展了我的 'ggpmisc' 包,其中包含一些函数来操作 ggplot 对象中的图层(目前在​​包 'gginnards' 中)。这些函数是我之前对同一问题的回答中示例的更完善的版本。但是,请注意,在大多数情况下,这不是最好的工作方式,因为它违反了图形语法。在大多数情况下,可以使用 operator 以正常方式组装同一图形的不同变体+,可能将层组“打包”到列表中以具有组合构建块,从而可以简化复杂图形的组装。在特殊情况下,我们可能想要编辑现有绘图或更高级别函数的绘图输出,我们无法修改其定义。在这种情况下,这些图层操作功能可能很有用。上面的例子变成了。

library(gginnards)
p1 <- delete_layers(p, match_type = "GeomText")

有关其他示例,请参阅包的文档,以及有关可用于修改层顺序和在任意位置插入新层的伴随函数的信息。

于 2017-10-05T17:08:01.717 回答
4

@Kamil Slowikowski 谢谢!很有用。然而,我无法阻止自己在同一主题上创建一个新的变体......希望比原始帖子或 Kamil 的更新版本更容易理解,同时也避免了一些作业。

remove_geoms <- function(x, geom_type) {
  # Find layers that match the requested type.
  selector <- sapply(x$layers,
                     function(y) {
                       class(y$geom)[1] == geom_type
                     })
  # Delete the layers.
  x$layers[selector] <- NULL
  x
}

这个版本在功能上与Kamil的功能相同,所以上面的使用示例在此不再赘述。

顺便说一句,这个函数可以很容易地适应基于 stat 的类而不是 geom 的类来选择层。

remove_stats <- function(x, stat_type) {
  # Find layers that match the requested type.
  selector <- sapply(x$layers,
                     function(y) {
                       class(y$stat)[1] == stat_type
                     })
  # Delete the layers.
  x$layers[selector] <- NULL
  x
}
于 2017-09-14T22:36:31.750 回答
2

@Kamil 和@Pedro 非常感谢!对于那些感兴趣的人,还可以增加 Pedro 的函数以仅选择特定层,如下所示,带有一个last_only参数:

remove_geoms <- function(x, geom_type, last_only = T) {
  # Find layers that match the requested type.
  selector <- sapply(x$layers,
                     function(y) {
                       class(y$geom)[1] == geom_type
                     })
  if(last_only) 
    selector <- max(which(selector))
  # Delete the layers.
  x$layers[selector] <- NULL
  x
}

回到@Kamil 的示例情节:

set.seed(3000)
d <- data.frame(
  x = runif(10),
  y = runif(10),
  label = sprintf("label%s", 1:10)
)

p <- ggplot(d, aes(x, y, label = label)) + geom_point() + geom_point(color = "green") + geom_point(size = 5, color = "red")

p

在此处输入图像描述

p %>% remove_geoms("GeomPoint")

在此处输入图像描述

p %>% remove_geoms("GeomPoint")  %>% remove_geoms("GeomPoint")

在此处输入图像描述

于 2018-07-31T11:17:44.730 回答