如何确定GGPLOT2对象的每个层的的geom类型?(How to determine the ge

2019-07-03 23:09发布

作为一个努力消除来自我已经创建(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
}

Answer 1:

ggplot 2.2更新:如果你想要的是一个字符串,命名GEOM类型,你可以使用:

sapply(p$layers, function(x) class(x$geom)[1])

这产生用于每个层的的geom对象的第一类名。 在OP的例子:

[1] "GeomRibbon" "GeomLine" 

在上面不再是答案的代码给出了2.2的版本接受的答案产生两个NULL值显示的结果,以及对方的回答率全ggproto对象。



Answer 2:

编辑:这答案不再是当前。 它工作时,这个问题是后但与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 


Answer 3:

这里是看原对象的一种方式。 他们是环境,因为我的理解,所以在使用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"  


文章来源: How to determine the geom type of each layer of a ggplot2 object?