How to determine the geom type of each layer of a ggplot2 object?

て烟熏妆下的殇ゞ 提交于 2019-11-29 02:06:50

ggplot 2.2 update: If what you want is a character string naming the geom type, you can use:

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

which yields the first class name for the geom object of each layer. In the OP's example:

[1] "GeomRibbon" "GeomLine" 

The code in the answers above no longer give the results shown for version 2.2 The accepted answer yields two NULL values, and the other answer yields full ggproto objects.

Dason

Edit: This answer is no longer current. It worked when the question was asked and presumably for quite some time after but for an answer that works with ggplot2 >= 2.2.0 see https://stackoverflow.com/a/43982598/1003565


If we're just looking to get the geom name for each item this appears to be in the $geom$objname part of each layer.

p$layers[[1]]$geom$objname
#[1] "ribbon"
lapply(p$layers, function(x){x$geom$objname})
#[[1]]
#[1] "ribbon"
#
#[[2]]
#[1] "line"

As an added note - the reason you couldn't use the p$layers[[1]]$str() syntax is (probably) because you didn't explicitly load the proto package. ggplot2 uses it internally but it imports it instead of using Depends. Notice the difference:

> 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 

Here's one way of looking at proto objects. They are environments as I understand it, so using ls gives you the names (apparently even for items extracted from the parent environment which is the plot object, 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 points out that you might have wanted a character vector as a result, so using sapply with "[[" again should satisfy that possible desire:

 sapply( sapply( p$layers, "[[", "geom"), "[[", 'objname')
#[1] "ribbon" "line"

The changes in ggproto design consisted of making the names reside an extra layer deeper inside the 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"  
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!