Хранение объектов графика в списке
-
10-07-2019 - |
Вопрос
- Спросил я это вчерашний вопрос о сохранении графика внутри объекта.Я попытался реализовать первый подход (осознавая, что я не указал, что использую 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-файл с несколькими графиками на каждой странице, но основной целью моего кода было сохранить графики в списке, к которому я мог бы получить доступ позже.
Решение
Хорошо, итак, если ваша команда plot будет изменена на
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
.
Другие советы
Я думаю, вам следует использовать data
аргумент в qplot
, т.е. храните ваши векторы во фрейме данных.
Смотрите книгу Хэдли, раздел 4.4:
Ограничение на доступ к данным простое:это должен быть фрейм данных.Это ограничение, в отличие от других графических пакетов в R.Решетчатые функции могут принимать необязательный фрейм данных или использовать векторы непосредственно из глобальной среды....
Данные хранятся в объекте plot как копия, а не как ссылка.Это имеет два важных следствия:если ваши данные изменятся, график не будет отображаться;и объекты ggplot2 полностью автономны, так что их можно сохранить () на диск, а затем загрузить () и отобразить на графике, не требуя ничего другого из этого сеанса.
В вашем коде есть ошибка, касающаяся подписки на список.Это должно быть
pltList[[pltName]]
нет
pltList[pltName]
Примечание:
class(pltList[1])
[1] "list"
pltList[1] - это Список содержащий первый элемент pltList.
class(pltList[[1]])
[1] "ggplot"
pltList[[1]] является первым элемент из pltList.
Ваш второй вопрос: многостраничные PDF-файлы просты - см. 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 ()
возвращает объект, который вы можете сохранить и получить. Р>
Еще одно предложение, касающееся вашего второго вопроса, - использовать Sweave или Brew, поскольку они дадут вам полный контроль над отображением многостраничного PDF-файла.
Посмотрите этот связанный с этим вопрос .