2012-11-19 10 views
6

Come parte di uno sforzo per rimuovere una geom specifica da un grafico che ho già creato (SO link here), mi piacerebbe determinare dinamicamente il tipo di geom di ogni livello di un oggetto ggplot2.Come determinare il tipo di geom di ogni livello di un oggetto ggplot2?

Supponendo che non conosca l'ordine in cui ho aggiunto i livelli, esiste un modo per trovare dinamicamente i livelli con una geom specifica? Se stampo i livelli come faccio di seguito, posso vedere che i livelli sono memorizzati in un elenco, ma non riesco ad accedere al tipo di 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) 

Non ho dimestichezza con gli oggetti Proto e le cose che ho provato dal proto documentation non sembra funzionare (ad esempio p$layers[[1]]$str()).


Grazie alle risposte qui sotto sono stato in grado di venire con una funzione che elimina uno strato dinamico:

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

Proprio come un ulteriore vantaggio è possibile fornire un piccolo insieme di dati riproducibili con il vostro codice? – Dason

+0

Whoops, copia-incolla fallisce. Grazie, @Dason –

risposta

4

ggplot 2.2 update: Se quello che vuoi è una stringa di caratteri denominazione del tipo geom, si può usare:

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

da cui si ricava il primo nome della classe per l'oggetto geom di ogni strato. Nell'esempio dell'OP:

[1] "GeomRibbon" "GeomLine" 

Il codice nelle risposte sopra non fornisce più i risultati mostrati per la versione 2.2 La risposta accettata restituisce due valori NULL e l'altra risposta produce gli oggetti completi ggproto.

+0

Qualche idea su quale versione ha infranto il codice nella mia risposta? – Dason

+0

Non lo so per certo, ma la versione 2 di dicembre 2015 ha introdotto una serie di importanti cambiamenti, quindi forse? https://blog.rstudio.org/2015/12/21/ggplot2-2-0-0/ – arvi1000

+1

Probabilmente era così. In entrambi i casi ho aggiunto una modifica alla parte superiore del mio post che reindirizza alla tua risposta poiché sembra essere aggiornata. – Dason

4

Edit: Questa risposta non è più attuale. Ha funzionato quando la domanda è stato chiesto e presumibilmente per un bel po 'di tempo dopo, ma per una risposta che funziona con ggplot2> = 2.2.0 vedono https://stackoverflow.com/a/43982598/1003565


Se stiamo solo cercando di ottenere il nome geom per ogni questo elemento sembra essere nella parte $ geom $ objname di ogni livello.

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

Come nota aggiunto - il motivo per cui non è possibile utilizzare la sintassi p$layers[[1]]$str() è (probabilmente) perché non hai caricato in modo esplicito il pacchetto proto. ggplot2 lo usa internamente ma lo importa invece di usare Depends. Notare la differenza:

> 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

Grazie per aver spiegato perché '$ str()' non era disponibile. –

+0

(cinque anni dopo, questo non funziona più per la versione corrente di ggplot, ha inviato una nuova risposta) – arvi1000

2

Ecco un modo di guardare gli oggetti prototipo. Essi sono gli ambienti a quanto mi risulta, in modo da utilizzare ls ti dà i nomi (a quanto pare anche per gli elementi estratti dall'ambiente madre che è l'oggetto trama, 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 sottolinea che si potrebbe avere voleva un carattere vettoriale di conseguenza, in modo da utilizzare sapply con "[[" ancora una volta dovrebbe soddisfare quel desiderio possibile:

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

i cambiamenti nella progettazione ggproto consisteva di fare i nomi risiedono un ulteriore livello più profondo all'interno delle 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

La tua call di zaffo restituisce ancora oggetti di prototipo anche se non è l'ideale per lavorare con. Se prendi la parte objname di ciò che ritorni, ottieni invece una bella stringa di caratteri. – Dason

+0

risolto quella carenza. –

Problemi correlati