2009-11-30 18 views
10

Zapytałem wczoraj o pytanie dotyczące przechowywania wykresu w obiekcie. Próbowałem wdrożyć pierwsze podejście (mając świadomość, że nie sprecyzowałem, że używałem qplot() w moim oryginalnym pytaniu) i zauważyłem, że nie działa zgodnie z oczekiwaniami.Przechowywanie obiektów fabuły na liście

library(ggplot2)    # add ggplot2 

string = "C:/example.pdf"  # Setup pdf 
pdf(string,height=6,width=9) 

x_range <- range(1,50)   # Specify Range 

# Create a list to hold the plot objects. 
pltList <- list() 
pltList[] 

for(i in 1 : 16){ 

# Organise data 
y = (1:50) * i * 1000      # Get y col 
x = (1:50)         # get x col 
y = log(y)         # Use natural log 

# Regression 
lm.0 = lm(formula = y ~ x)     # make linear model 
inter = summary(lm.0)$coefficients[1,1]  # Get intercept 
slop = summary(lm.0)$coefficients[2,1]  # Get slope 

# Make plot name 
pltName <- paste('a', i, sep = '') 

# make plot object  
p <- qplot(
    x, y, 
    xlab = "Radius [km]", 
    ylab = "Services [log]", 
    xlim = x_range, 
    main = paste("Sample",i) 
) + geom_abline(intercept = inter, slope = slop, colour = "red", size = 1)   

print(p)  

pltList[[pltName]] = p  
} 

# close the PDF file 
dev.off() 

W tym przypadku użyłem numerów próbek, aby kod działał, jeśli został właśnie skopiowany. Spędziłem kilka godzin zastanawiając się nad tym, ale nie wiem, co się dzieje. Napisał pierwszy zestaw plików PDF bez problemu, więc mam 16 plików pdf z prawidłowymi działkami.

wtedy, gdy używam ten kawałek kodu:

string = "C:/test_tabloid.pdf" 
pdf(string, height = 11, width = 17) 

grid.newpage() 
pushViewport(viewport(layout = grid.layout(3, 3))) 

vplayout <- function(x, y){viewport(layout.pos.row = x, layout.pos.col = y)} 

counter = 1 

# Page 1 
for (i in 1:3){  
    for (j in 1:3){  
     pltName <- paste('a', counter, sep = '') 
     print(pltList[[pltName]], vp = vplayout(i,j)) 
     counter = counter + 1 
    } 
} 

dev.off() 

wynik otrzymuję to ostatnia linia modelu liniowego (abline) na każdym wykresie, ale dane nie zmienia. Kiedy sprawdzam moją listę działek, wydaje się, że wszystkie z nich zostały nadpisane przez najnowszy wykres (z wyjątkiem obiektu abline).

Mniej ważna kwestia wtórna polegała na tym, jak wygenerować wielomiejscowy plik pdf z kilkoma działkami na każdej stronie, ale głównym celem mojego kodu było przechowywanie działek na liście, do której mogłem uzyskać dostęp w późniejszym terminie.

Odpowiedz

10

Ok, więc jeśli komenda fabuła zmienia się na

p <- qplot(data = data.frame(x = x, y = y), 
      x, y, 
      xlab = "Radius [km]", 
      ylab = "Services [log]", 
      xlim = x_range, 
      ylim = c(0,10), 
      main = paste("Sample",i) 
      ) + geom_abline(intercept = inter, slope = slop, colour = "red", size = 1)   

wtedy wszystko działa zgodnie z oczekiwaniami. Oto, co podejrzewam, że się dzieje (chociaż Hadley prawdopodobnie mógł to wyjaśnić). Kiedy ggplot2 "zapisuje" dane, to w rzeczywistości zapisuje ramkę danych i nazwy parametrów. Więc dla polecenia jak dałem go, masz

> summary(pltList[["a1"]]) 
data: x, y [50x2] 
mapping: x = x, y = y 
scales: x, y 
faceting: facet_grid(. ~ ., FALSE) 
----------------------------------- 
geom_point: 
stat_identity: 
position_identity: (width = NULL, height = NULL) 

mapping: group = 1 
geom_abline: colour = red, size = 1 
stat_abline: intercept = 2.55595281266726, slope = 0.05543539319091 
position_identity: (width = NULL, height = NULL) 

Jednakże, jeśli nie zostanie określony parametr w qplot data, wszystkie zmienne się oceniać w bieżącym zakresie, ponieważ nie ma załączony (czytaj : zapisana) ramka danych.

data: [0x0] 
mapping: x = x, y = y 
scales: x, y 
faceting: facet_grid(. ~ ., FALSE) 
----------------------------------- 
geom_point: 
stat_identity: 
position_identity: (width = NULL, height = NULL) 

mapping: group = 1 
geom_abline: colour = red, size = 1 
stat_abline: intercept = 2.55595281266726, slope = 0.05543539319091 
position_identity: (width = NULL, height = NULL) 

Więc gdy działka jest generowany po raz drugi wokół, zamiast oryginalne wartości, używa aktualnych wartości x i y.

+0

Dzięki RCS i Jonathan rozwiązały ten problem. Nie wiedziałem o argumencie danych i o tym, jak można go wykorzystać do przechowywania danych. Teraz sprawdzam tę część książki. – womble

1

Na drugie pytanie: wielostronicowe pliki PDF są łatwe - patrz help(pdf):

onefile: logical: if true (the default) allow multiple figures in one 
      file. If false, generate a file with name containing the 
      page number for each page. Defaults to ‘TRUE’. 

Na głównym pytaniem, ja nie rozumiem, jeśli chcesz zapisać Wejścia wykreślić na liście do późniejszego przetwarzania lub do wydruków wyjściowych. Jeśli jest to drugie, nie jestem pewien, czy plot() zwraca obiekt, który można przechowywać i pobierać.

+0

Miałem nadzieję na przechowywanie wydruków wyjściowych. Czy jeśli przechowuję dane wejściowe na wykresie, czy zawierają one wartości x i y w tym konkretnym czasie? – womble

+0

Oczywiście. Po prostu przechowuj wszystkie argumenty funkcji itp. Na liście. To jest bardzo standardowe. Ale twoje założenie o przechowywaniu _plot output_ nie jest. Wyniki wydruku są zależne od urządzenia i najprawdopodobniej zależne od systemu operacyjnego. Po prostu napisz do pliku, ewentualnie mapy bitowej, i pokaż to. Lub napisz aplikacje w stylu GUI. Lub po prostu otwórz wiele okien wydruku. –

+0

Jednak 'ggplot' może również zwracać obiekty do ciebie. W takim przypadku odpowiedź Eduardo jest twoim kluczem. –

2

W Twoim kodzie występuje błąd związany z subskrybowaniem list. Powinno być

pltList[[pltName]] 

nie

pltList[pltName] 

Uwaga:

class(pltList[1]) 
[1] "list" 

pltList [1] jest lista zawierający pierwszy element pltList.

class(pltList[[1]]) 
[1] "ggplot" 

pltList [[1]] Jest to pierwsza elementem z pltList.

+0

Przepraszam - popełniłem błąd, co miałem zamiar wkleić. Nie do końca zrozumiałem różnicę między składnię i edytowałem ją, aby zobaczyć różnicę. Jednak mój błąd nadal istnieje, jak opisałem powyżej. – womble

1

Inną propozycją dotyczącą drugiego pytania jest użycie opcji Sweave lub Brew, ponieważ daje to pełną kontrolę nad wyświetlaniem wielostronicowego pliku pdf.

Spójrz na at this related question.

4

Myślę, że powinieneś użyć argumentu data w qplot, tj. Przechowywać swoje wektory w ramce danych.

Zobacz książkę Hadleya, Rozdział 4.4:

Ograniczenie danych jest proste: musi to być ramka danych. Jest to restrykcyjne, w przeciwieństwie do innych pakietów graficznych w funkcjach R. Lattice może przyjmować opcjonalną ramkę danych lub wykorzystywać wektory bezpośrednio ze środowiska globalnego. ...

Dane są przechowywane w obiekcie wydruku jako kopia, a nie jako odniesienie. Ma to dwie ważne konsekwencje: jeśli twoje dane się zmienią, fabuła się nie zmieni; Obiekty ggplot2 są całkowicie autonomiczne, dzięki czemu można je zapisać() na dysku, a następnie wczytać() i wydrukować bez potrzeby wykonywania innych czynności z tej sesji.

Powiązane problemy