Zapisz wykres w obiekcie

83

W programie ggplot2można łatwo zapisać grafikę do obiektu R.

p = ggplot(...) + geom_point()      # does not display the graph
p                                   # displays the graph

Funkcja standardowa plottworzy grafikę jako funkcję void i zwraca NULL.

p = plot(1:10)     # displays the graph
p                  # NULL

Czy można zapisać grafikę stworzoną przez plotw obiekcie?

Remi.b
źródło
plotjest typem ogólnym i ploto ile wiem , różne metody zwracają takie obiekty. plot.defaultjednak rzeczywiście powraca NULL.
Konrad Rudolph
Czy Twoim celem jest możliwość ponownego przesłania wykresu dopiero ppo wpisaniu go jako obiektu? A może chciałbyś go zapisać jako obiekt, który następnie mógłbyś zmienić na przykład jego wartości?
LyzandeR
Mogę chcieć nałożyć inną grafikę na zapisaną grafikę, ale nie zamierzam modyfikować wykresu, który został utworzony i zapisany. Czy odpowiedziałem na twoje pytanie? Thks
Remi. B
@ Remi.b Dziękuje. Opublikowałem rozwiązanie, które może pomóc.
LyzandeR

Odpowiedzi:

95

grafika bazowa rysowana bezpośrednio na urządzeniu.

Możesz użyć

1- recordPlot

2- Niedawno wprowadzony gridGraphicspakiet do konwersji grafiki podstawowej do ich odpowiednika w siatce

Oto minimalny przykład,

plot(1:10) 

p <- recordPlot()
plot.new() ## clean up device
p # redraw

## grab the scene as a grid object
library(gridGraphics)
library(grid)
grid.echo()
a <- grid.grab()

## draw it, changes optional
grid.newpage()
a <- editGrob(a, vp=viewport(width=unit(2,"in")), gp=gpar(fontsize=10))
grid.draw(a)
baptiste
źródło
1
Nie jest dla mnie jasne: czy (1) i (2) oddzielne metody osiągnięcia tego samego celu, czy też dwa kroki są niezbędne, aby odpowiedzieć na pytanie PO?
NLi10Me
@ NLi10Me 2 różne metody.
zx8754
Jeśli spróbuję saveRDS(object = p, file = "p.Rds"), a następnie załaduję nową sesję języka R, uruchom, p <- readRDS(file = "p.Rds")a następnie ppojawi się komunikat o błędzie Error in replayPlot(x) : loading snapshot from a different session. Czy pniepoprawnie zapisuję obiekt?
user5359531
Wygląda na to, że błąd, który otrzymywałem, został rozwiązany w R 3.3.0 , używając tej wersji działa. Kiedy użyłem gridGraphicspokazanej tutaj metody, kolory na przerysowanym wykresie ciągle się pomieszały, nawet zgrid.grab(wrap=TRUE)
user5359531
34

Bardzo się na to spóźniłem, ale było to pierwsze pytanie, które się pojawiło, gdy szukałem tego pytania. Dlatego chciałbym dodać moje rozwiązanie dla przyszłych widzów, którzy napotkają to pytanie.

Rozwiązałem to, używając funkcji zamiast obiektu. Załóżmy na przykład, że chcemy porównać dwa rozkłady beta z różnymi parametrami. Uciekamy:

z1<-rbeta(10000,5,5)
z2<-rbeta(10000,20,20)
plotit<-function(vector,alpha,beta){
plot(density(vector),xlim=c(0,1))
abline(v=alpha/(alpha+beta),lty="longdash")
}

I zapisuj wykresy jako funkcje, a nie obiekty.

z.plot1<-function(){plotit(z1,5,5)}
z.plot2<-function(){plotit(z2,20,20)}

Następnie możemy nazwać każdy wykres tak, jak chcemy, po prostu nazywając te dwa wykresy funkcjami, a nie obiektami.

z.plot1()

kreśli pierwszą działkę i

z.plot2()

kreśli drugą.

Mam nadzieję, że pomoże to komuś, kto natknie się na to później!

koło wozu
źródło
To jest bardzo przydatne! Myślę, że to świetny pomysł, aby przygotować gotowe wykresy, tego właśnie szukałem
Jojostack
To genialne podejście bazowe R! recordPlotjest zdecydowanie przydatny (jeśli masz już otwarte okno), ale ta odpowiedź jest dokładnie tym, czego szukają ludzie, odwiedzając ten post. +1!
leśnik
Szczególnie przydatne w przypadku złożonych, wielokrotnych działek.
Joe
Dołączę do chóru ludzi, którzy naprawdę doceniają tę sztuczkę. Również w imieniu moich uczniów :-)
Laryx Decidua 26.07.19
Leksykalny zakres znowu na ratunek! :)
Jason
17

Możesz użyć funkcji aktywnego wiązania pryrpakietu, jeśli nie chcesz bezpośrednio zmieniać wartości utworzonego obiektu.

library(pryr)
a %<a-% plot(1:10,1:10)

Za każdym razem, gdy będziesz pisać ana konsoli, wykres zostanie ponownie wydrukowany na ekranie. %<a-%Operator będzie ponownie uruchomić skrypt za każdym razem (w przypadku jednego wykresu To nie jest problem, myślę). Zasadniczo więc za każdym razem, gdy użyjesz akodu, zostanie uruchomiony ponownie, co spowoduje powstanie wykresu, którym możesz oczywiście manipulować (nałożyć inny wykres na górę) lub zapisać, używając pngna przykład. aJednak żadna sama wartość nie zostanie zapisana . Wartość nadal będzie NULL.

Nie wiem, czy powyższe jest tym, czego szukasz, ale może to być akceptowalne rozwiązanie.

LyzandeR
źródło
Dziękuję Ci. To bardzo przydatne rozwiązanie. Czy wiesz, czy to zadziała, jeśli działka składa się z kilku linii (takich jak plot(1:10);abline(v=4)na przykład)? +1
Remi. B Kwietnia
@ Remi.b Tak, oczywiście, że tak. Musisz to jednak wpisać w ten sposób a %<a-% {plot(1:10);abline(v=4)}. ” Jeśli wpiszesz to w tych nawiasach klamrowych, możesz mieć tyle wierszy, ile chcesz! Ponadto, jeśli chcesz ponownie przypisać wartość doa , musisz ją najpierw usunąć za pomocą, rm(a)a następnie ponownie przypisać %<a-%operator inaczej dostaniesz ostrzeżenie nie wiem, dlaczego tak się dzieje, ale myślę, że nie jest to nic wielkiego..
LyzandeR
To jest naprawdę fajne! Będę musiał trochę poczytać o tym pakiecie, ponieważ wydaje mi się, że niemożliwe jest zrobienie tego, co robi ta dziwna funkcja %<a-%. Dzięki
Remi. B Kwietnia
Tak, to kolejny z tych naprawdę fajnych paczek, które zrobił Hadley. Jest to zestaw funkcji, które pozwalają dogłębnie zrozumieć język R. Przyjrzyj się %<d-%też, może się później przydać. Cieszę się, że mogłem być pomocny :)
LyzandeR
1
@LyzandeR czy można połączyć zapisane działki w multiplot?
user2300940
-4
library(ggplot2)
# if mygraph is a plot object
ggsave("myplot1.png",mygraph)

# if the plot is in a list (e.g. created by the Bibliometrics package)
ggsave("myplot1.png",mygraphs[[1]])
Dr T.
źródło
Chociaż Twoja odpowiedź wygląda na „poprawną” (ale nie jestem programistą R), normalną praktyką w przypadku przepełnienia stosu jest dodawanie tekstu wyjaśniającego, a nie tylko umieszczanie „zwięzłego” bloku zawierającego tylko kod. To sprawia, że ​​odpowiedź jest bardziej wartościowa w dłuższej perspektywie i dla szerszego grona użytkowników. (Ale i tak miej za sobą głos!)
Adrian Mole
3
OP pytał, jak to zrobić bez użycia ggplot2.
Jason