2012-11-19 13 views
6

W ramach usiłowania usunięcia określonego Geom z działki, którą już utworzyłem (SO link here), chciałbym dynamicznie określić typ geom każdej warstwy obiektu ggplot2.Jak określić typ geometrii każdej warstwy obiektu ggplot2?

Zakładając, że nie znam kolejności dodawania warstw, czy istnieje sposób na dynamiczne znajdowanie warstw o ​​określonej geometrii? Jeśli wydrukuję warstwy takie jak poniżej, widzę, że warstwy są przechowywane na liście, ale nie mogę uzyskać dostępu do typu 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) 

nie jestem zaznajomiony z obiektami proto i rzeczy próbowałem z proto documentation nie wydają się działać (np p$layers[[1]]$str()).


Dzięki odpowiedzi poniżej byłem w stanie wymyślić funkcji, która usuwa warstwę dynamicznie:

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

Czy dla wygody można podać mały powtarzalny zestaw danych wraz z kodem? – Dason

+0

Ups, copy-paste fail. Dzięki, @Dason –

Odpowiedz

4

ggplot 2,2 zmiana: Jeśli to, co chcesz, to ciąg znaków nazewnictwa typu geom, można użyć:

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

co daje pierwszą nazwę klasy dla obiektu geom każdej warstwy. W przykładzie OP:

[1] "GeomRibbon" "GeomLine" 

Kod w powyższych odpowiedziach nie daje już wyników pokazanych dla wersji 2.2 Przyjęta odpowiedź daje dwie wartości NULL, a druga odpowiedź daje pełne obiekty ggproto.

+0

Jakieś pomysły, która wersja złamała kod w mojej odpowiedzi? – Dason

+0

Nie wiem na pewno, ale wersja 2 z grudnia 2015 roku wprowadziła kilka poważnych zmian, więc może to? https://blog.rstudio.org/2015/12/21/ggplot2-2-0-0/ – arvi1000

+1

To było prawdopodobnie to. Tak czy inaczej dodałem edycję na początku mojego przekierowania do Twojej odpowiedzi, ponieważ wydaje się być aktualna. – Dason

4

Edit: Ta odpowiedź nie jest już aktualny. To działało, gdy padło pytanie i zapewne przez jakiś czas po tym, ale na odpowiedź, który współpracuje z ggplot2> = 2.2.0 zobaczyć https://stackoverflow.com/a/43982598/1003565


Jeśli szukasz po prostu uzyskać nazwę geom dla każdego element wydaje się znajdować w części $ geom $ objname każdej warstwy.

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

Jako dodatkowy Uwaga - Dlatego nie można używać składni p$layers[[1]]$str() jest (chyba), bo nie jawnie załadować pakiet proto. ggplot2 używa go wewnętrznie, ale importuje go zamiast używać Depend. Zauważ różnicę:

> 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

Dzięki za wyjaśnienie, dlaczego '$ str()' nie był dostępny. –

+0

(pięć lat później to już nie działa dla aktualnej wersji ggplot, opublikował nową odpowiedź) – arvi1000

2

Oto jeden sposób patrzenia na obiekty proto. Są środowiska, jak ja to rozumiem, więc korzystanie ls daje nazwiska (podobno nawet do przedmiotów wydobytych z otoczenia dominującej będącej przedmiotem działka, 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 wskazuje, że może mieć chciał wektor znaków w wyniku, więc korzystanie sapply z „[[” ponownie powinien spełniać to możliwe pragnienie:

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

zmiany w konstrukcji ggproto składało dokonywania nazwy pobytu dodatkową warstwę głębiej wewnątrz 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

Twoje połączenie sapply nadal zwraca obiekty proto, co nie jest idealne do pracy. Jeśli weźmiesz objname część tego, co powrócisz, otrzymasz zamiast tego fajny ciąg znaków. – Dason

+0

naprawił to niedociągnięcie. –