Хранение объектов графика в списке - PullRequest
11 голосов
/ 30 ноября 2009

Вчера я задал этот вопрос о сохранении графика внутри объекта. Я попытался реализовать первый подход (понимая, что я не указал, что я использовал qplot() в своем исходном вопросе), и заметил, что он не работает должным образом.

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

Я использовал номера образцов в этом случае, поэтому код запускается, если он только что скопирован. Я провел несколько часов, ломая голову над этим, но я не могу понять, что происходит не так. Он пишет первый набор файлов PDF без проблем, поэтому у меня есть 16 файлов PDF с правильными графиками.

Тогда, когда я использую этот кусок кода:

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

В результате я получаю последнюю линейную модельную линию (abline) на каждом графике, но данные не меняются. Когда я проверяю свой список графиков, кажется, что все они перезаписываются самым последним графиком (за исключением объекта abline).

Менее важный дополнительный вопрос заключался в том, как создать многостраничный PDF-файл с несколькими графиками на каждой странице, но основная цель моего кода состояла в том, чтобы сохранить графики в списке, к которому я смогу получить доступ позже.

Ответы [ 5 ]

10 голосов
/ 30 ноября 2009

Хорошо, так что если ваша команда заговора изменена на

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)           

тогда все работает как положено. Вот что я подозреваю, что происходит (хотя Хэдли, вероятно, могла бы прояснить ситуацию). Когда ggplot2 «сохраняет» данные, фактически он сохраняет фрейм данных и имена параметров. Таким образом, за команду, как я дал, вы получите

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

Однако, если вы не укажете параметр data в qplot, все переменные будут оценены в текущей области, потому что нет прикрепленного (читай: сохраненного) фрейма данных.

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)

Таким образом, когда график создается во второй раз, вместо использования исходных значений, он использует текущие значения x и y.

4 голосов
/ 30 ноября 2009

Я думаю, вы должны использовать аргумент data в qplot, т.е. хранить ваши векторы в кадре данных.

См. Книгу Хэдли, раздел 4.4:

Ограничение на данные простое: это должен быть фрейм данных. Это ограничительно, и в отличие от других графических пакетов в R. Функции решетки могут принимать необязательный фрейм данных или использовать векторы непосредственно из глобальной среды. ...

Данные хранятся в объекте графика как копия, а не как ссылка. Это имеет два важные последствия: если ваши данные изменятся, сюжет не изменится; и объекты ggplot2 полностью автономны, поэтому их можно сохранять () d на диск, а затем загружать (), редактировать и печатать, не требуя ничего другого из этого сеанса.

2 голосов
/ 30 ноября 2009

В вашем коде есть ошибка, связанная с подпиской на список. Должно быть

pltList[[pltName]]

не

pltList[pltName]

Примечание:

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

pltList [1] - это список , содержащий первый элемент pltList.

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

pltList [[1]] является первым элементом pltList.

1 голос
/ 30 ноября 2009

Другим предложением относительно вашего второго вопроса будет использование Sweave или Brew, поскольку они дадут вам полный контроль над отображением многостраничного pdf.

Посмотрите на этот связанный вопрос .

1 голос
/ 30 ноября 2009

По второму вопросу: многостраничные pdfs просты - см. 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’.

По вашему основному вопросу, я не понимаю, хотите ли вы сохранить график вводит в список для последующей обработки или выводит график .Если это последнее, я не уверен, что plot() возвращает объект, который вы можете сохранить и получить.

...