作为一个努力消除来自我已经创建(SO链接情节特定GEOM的一部分在这里 ),我想动态确定GGPLOT2对象的每一层的GEOM类型。
假设我不知道我在其中添加图层顺序,是有没有办法动态查找与特定GEOM几层? 如果我打印出来的层像我这样做我下面可以看到,各层都存储在一个名单,但我似乎无法访问GEOM类型。
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()
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$layers[[1]]$str()
由于下面我的答案是能够拿出一个函数,动态地去除一层:
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
}
ggplot 2.2更新:如果你想要的是一个字符串,命名GEOM类型,你可以使用:
sapply(p$layers, function(x) class(x$geom)[1])
这产生用于每个层的的geom对象的第一类名。 在OP的例子:
[1] "GeomRibbon" "GeomLine"
在上面不再是答案的代码给出了2.2的版本接受的答案产生两个NULL值显示的结果,以及对方的回答率全ggproto
对象。
编辑:这答案不再是当前。 它工作时,这个问题是后但与GGPLOT2问题的解答> = 2.2.0见问想必相当长的一段时间https://stackoverflow.com/a/43982598/1003565
如果我们只是希望为每个项目获得的geom的名字,这似乎是在每一层的$ GEOM $ objname表的一部分。
p$layers[[1]]$geom$objname
#[1] "ribbon"
lapply(p$layers, function(x){x$geom$objname})
#[[1]]
#[1] "ribbon"
#
#[[2]]
#[1] "line"
作为一个补充说明-你不能使用的原因p$layers[[1]]$str()
语法(可能),因为你没有明确地加载原包装。 GGPLOT2在内部使用它,但它导入它,而不是使用depends的。 注意区别:
> 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()
> 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$layers[[1]]$str()
Error: attempt to apply non-function
> library(proto)
> p$layers[[1]]$str()
proto object
$ geom_params:List of 2
$ mapping :List of 2
$ stat_params: Named list()
$ stat :proto object
..parent: proto object
.. .. parent: proto object
$ inherit.aes: logi TRUE
$ geom :proto object
..parent: proto object
.. .. parent: proto object
$ position :proto object
..parent: proto object
.. .. parent: proto object
.. .. .. parent: proto object
$ subset : NULL
$ data : list()
..- attr(*, "class")= chr "waiver"
$ show_guide : logi NA
这里是看原对象的一种方式。 他们是环境,因为我的理解,所以在使用ls
让你的名字(甚至显然从中是剧情对象父环境,提取的项目p
。):
ls(p$layers[[1]])
# [1] "data" "geom" "geom_params" "inherit.aes" "mapping"
# [6] "position" "show_guide" "stat" "stat_params" "subset"
p$layers[[1]][["geom"]]
#geom_ribbon:
sapply( p$layers, "[[", "geom")
#---------------
[[1]]
geom_ribbon:
[[2]]
geom_line:
@Dason指出,你可能因此使用sapply与一直想一个特征向量,结果,“[”再次应满足这一愿望可能:
sapply( sapply( p$layers, "[[", "geom"), "[[", 'objname')
#[1] "ribbon" "line"
在ggproto设计的变化包括使名驻留额外的更深一层里面的class
-attributes:
lapply( sapply( p$layers, "[[", "geom"), function(x) attributes(x) )
#----------------
[[1]]
[[1]]$class
[1] "GeomRibbon" "Geom" "ggproto"
[[2]]
[[2]]$class
[1] "GeomLine" "GeomPath" "Geom" "ggproto"
sapply( sapply( p$layers, "[[", "geom"), function(x) class(x)[[1]][1] )
[1] "GeomRibbon" "GeomLine"