2012-11-19 29 views
6

作爲從我已經創建的圖中刪除特定幾何的工作的一部分(我的鏈接here),我想動態確定ggplot2對象的每個圖層的幾何類型。如何確定一個ggplot2對象的每個圖層的幾何類型?

假設我不知道我添加圖層的順序,有沒有一種方法來動態查找具有特定幾何圖形的圖層?如果我像下面這樣打印圖層,我可以看到圖層存儲在一個列表中,但我似乎無法訪問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) 

我不熟悉,我從原似乎documentation不工作(例如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 
} 
+0

正如增加一個便利,您可以提供一個小的可重複數據集以及您的代碼? – Dason

+0

哎呀,複製粘貼失敗。謝謝,@Dason –

回答

4

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

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

其產生一流的名字爲每一層的GEOM對象。在OP的例子中:

[1] "GeomRibbon" "GeomLine" 

以上答案中的代碼不再給出第2版顯示的結果。2接受的答案產生兩個NULL值,另一個答案產生完整的ggproto對象。

+0

任何想法哪個版本打破了我的答案中的代碼? – Dason

+0

我不知道,但2015年12月的第2版引入了一系列重大變化,所以也許呢? https://blog.rstudio.org/2015/12/21/ggplot2-2-0-0/ – arvi1000

+1

這可能是它。無論哪種方式,我添加了一個編輯到我的文章的頂部重定向到您的答案,因爲它似乎是最新的。 – Dason

4

編輯:這個答案不再是當前。它工作時,這個問題是後但與GGPLOT2問題的解答要求想必很長一段時間> = 2.2.0看到https://stackoverflow.com/a/43982598/1003565


如果我們只是希望得到每個GEOM名item看起來在每個圖層的$ 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 
+1

感謝您解釋爲什麼'$ str()'不可用。 –

+0

(五年之後,這不再適用於當前的ggplot版本;發佈了一個新答案) – arvi1000

2

以下是查看原始對象的一種方法。他們是環境,因爲我的理解,所以在使用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" 
+0

雖然這不適合與您一起工作,但您的sapply調用仍會返回原始對象。如果你抓住你返回的objname部分,那麼你會得到一個漂亮的字符串。 – Dason

+0

解決了這個缺陷。 –

相關問題