2012-11-15 15 views
22

Chciałbym usunąć layer (w tym przypadku wyniki geom_ribbon) z obiektu siatki utworzonego przez ggplot2. Czy istnieje sposób, w jaki mogę go usunąć, skoro jest już częścią obiektu?Usuń warstwę z wykresu ggplot2

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() 

# This has the geom_ribbon 
p 

# This overlays another ribbon on top 
p + geom_ribbon(aes(ymin=ymin, ymax=ymax, fill=NA)) 

Chciałbym tej funkcjonalności, aby umożliwić mi tworzenie bardziej skomplikowanych działek na mniej skomplikowanych. Używam funkcji, które zwracają obiekt siatki, a następnie drukują końcowy wykres po jego całkowitym złożeniu. Podstawowy wykres ma pojedynczą linię z odpowiadającym mu słupkiem błędu (geom_ribbon). Bardziej skomplikowany wątek będzie miał kilka linii, a liczne nakładające się obiekty będą się rozpraszać. Chciałbym je usunąć z działek z wieloma liniami. Dodatkowo będę mógł szybko tworzyć alternatywne wersje wykorzystujące aspekty lub inną funkcjonalność ggplot2.


Edit: Przyjmowanie odpowiedź @ mnel jako to działa. Teraz muszę ustalić, jak uzyskać dynamiczny dostęp do warstwy geom_ribbon, która jest przechwytywana w pytaniu SO here.


Edit 2: Dla kompletności, jest to funkcja stworzyłem, aby rozwiązać ten problem:

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 możesz opisać przypadek użycia, w którym możesz go użyć? – Andrie

+0

Odnalezienie konkretnej warstwy wewnątrz 'p $ layers', a następnie jej zatarcie przez przypisanie jej wartości' NULL' prawdopodobnie "zadziałałoby", ale nie przewiduję niezawodności. – joran

+0

Chyba nie rozumiem tego prawa. Jeśli musisz go mieć, ale nie chcesz go zobaczyć, dlaczego nie "alpha = 0"? – Mikko

Odpowiedz

5

Dla wersji ggplot2 2.2.1, musiałem zmodyfikować proponowaną remove_geom funkcję tak:

remove_geom <- function(ggplot2_object, geom_type) { 
    # Delete layers that match the requested type. 
    layers <- lapply(ggplot2_object$layers, function(x) { 
    if (class(x$geom)[1] == geom_type) { 
     NULL 
    } else { 
     x 
    } 
    }) 
    # Delete the unwanted layers. 
    layers <- layers[!sapply(layers, is.null)] 
    ggplot2_object$layers <- layers 
    ggplot2_object 
} 

Oto przykład, w jaki sposób z niego korzystać:

library(ggplot2) 

set.seed(3000) 
d <- data.frame(
    x = runif(10), 
    y = runif(10), 
    label = sprintf("label%s", 1:10) 
) 

p <- ggplot(d, aes(x, y, label = label)) + geom_point() + geom_text() 

Pokażmy oryginalny działki:

p 

plot with text labels

Teraz usuń etykiety i pokaż działkę ponownie:

p <- remove_geom(p, "GeomText") 
p 

plot without text labels

16

Jeśli spojrzeć na

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) 

widać, że chcesz usunąć pierwszą warstwę

Możesz to zrobić przez rede fining warstwy jako tylko drugi składnik na liście.

p$layer <- p$layer[2] 

Teraz budować i działka p

p 

Zauważ, że p$layer[[1]] <- NULL będzie działać jak również. Zgadzam się z komentarzami @Andrie i @ Joran dotyczącymi w tych przypadkach, które mogą być przydatne i nie wymagałyby, aby były one wiarygodne. enter image description here

+0

To również była moja myśl, ale nie testowałem jej w bardziej złożonych sytuacjach, w których usuwana warstwa mogła mieć powiązane skale, legendy itp. – joran

+0

Jeśli przyjrzeć się, jak działa 'ggplot_build', wszystko opiera się na składnik "warstw" działki, więc powinien być dość solidny (chyba że używałeś 'qplot', którego wewnętrznych czynności nie badałem.) – mnel

+0

Myślę, że możesz mieć rację; przynajmniej moje wstępne testy z bardziej skomplikowanymi fabułami zdawały się dobrze funkcjonować. – joran

1

@Kamil Słowikowski Dzięki! Bardzo przydatne. Nie mogłem jednak powstrzymać się od stworzenia nowej odmiany tego samego motywu ... mam nadzieję, że łatwiej to zrozumieć niż w oryginalnym poście lub zaktualizowanej wersji autorstwa Kamila, unikając także niektórych zadań.

remove_geoms <- function(x, geom_type) { 
    # Find layers that match the requested type. 
    selector <- sapply(x$layers, 
        function(y) { 
         class(y$geom)[1] == geom_type 
        }) 
    # Delete the layers. 
    x$layers[selector] <- NULL 
    x 
} 

Ta wersja jest funkcjonalnie identyczne z funkcją Kamila, więc przykład użycia powyżej nie trzeba powtarzać tutaj.

Ta funkcja może być z łatwością dostosowana do wyboru warstw w oparciu o klasę stat zamiast klasy geom.

remove_stats <- function(x, stat_type) { 
    # Find layers that match the requested type. 
    selector <- sapply(x$layers, 
        function(y) { 
         class(y$stat)[1] == stat_type 
        }) 
    # Delete the layers. 
    x$layers[selector] <- NULL 
    x 
} 
2

Jak ten problem wyglądał ciekawe, Rozszerzyliśmy paczkę „ggpmisc” z funkcjami do manipulowania warstw w obiekcie ggplot. Funkcje są bardziej dopracowanymi wersjami przykładu w mojej wcześniejszej odpowiedzi na to samo pytanie. Należy jednak pamiętać, że w większości przypadków nie jest to najlepszy sposób działania, ponieważ narusza Gramatyka grafiki. W większości przypadków można zestawiać różne wariacje tej samej postaci w normalny sposób z operatorem +, ewentualnie "pakując" grupy warstw w listy, aby połączyć bloki konstrukcyjne, które mogą uprościć montaż złożonych figur. Wyjątkowo możemy chcieć, aby istniejący wykres lub wydruk był tworzony przez funkcję wyższego poziomu, której definicji nie możemy zmodyfikować. W takich przypadkach przydatne mogą być te funkcje manipulacji warstwami. Powyższy przykład staje się.

library(ggpmisc) 
p1 <- delete_layers(p, match_type = "GeomText") 

znaleźć w dokumentacji pakietu dla innych przykładów i informacji na temat funkcji towarzyszących przydatnych modyfikacji kolejność warstw oraz do wstawiania nowych warstw w dowolnych pozycjach.

Powiązane problemy