Как узнать, завершен ли сюжет или нет
Обновление: я спросил Пола Меррелла ( "последний босс" ), и он сказал мне, что решение об открытии новой страницы сделано в src/library/graphics/src/graphics.c
на GNewPlot
:
pGEDevDesc GNewPlot(Rboolean recording)
Эффективно он смотрит на par(mfg)
и par(new)
, чтобы решить, следует ли открывать новую страницу. Как это сделать в дополнительном пакете?
Решение, использующее либо чистый R код, либо некоторый код C. Приемлемо.
knitr
использует пакет evaluate
для оценки фрагментов кода R и получения результатов, включая графики. Короче говоря, evaluate
вызывает recordPlot()
для записи моментального снимка текущего графика после того, как каждое выражение кода было оценено, а также когда отображаются крючки построения, такие как before.plot.new
и before.grid.newpage
(обычно это происходит перед новым графиком нарисован). Для тех, кто "Люк", используйте источник, если это недостаточно ясно.
После создания моментального снимка нам нужно решить, сохранять ли его, потому что моментальный снимок может не измениться после того, как мы оценим новое выражение, которое не связано с построением графика. Теперь вот моя проблема: когда сюжет содержит подзаголовки (например, pairs()
, coplot()
или par(mfrow = c(2, 3))
в базовой графике R), мы не должны сохранять неполные снимки. В приведенном ниже примере первые три графика следует отбросить:
par(mfrow = c(2, 2))
plot(rnorm(10))
plot(rnorm(10))
plot(rnorm(10))
plot(rnorm(10))
Для этого мы сравниваем par("mfg")[1:2]
с par("mfg")[3:4]
(как вы можете видеть в исходном коде), и это хорошо работает в некоторых случаях, но не для всех, например, issue # 25:
layout(matrix(c(1,3,2,3), 2))
plot(rnorm(10))
plot(rnorm(10))
plot(rnorm(10))
Теперь, как я узнаю, что сюжет не завершен до строки 4? Тройка mfg
больше не работает.
Я долго искал ответ на эту проблему, и я действительно буду признателен, если кто-нибудь может дать мне подсказку; более подробная информация приведена в двух ссылках выше, и я могу уточнить, что-то неясно. Я считаю, что должно существовать решение, потому что все устройства R знают, когда начинать новый экран или файл сюжета, а неполные графики не будут запускать новые экраны или файлы сюжета.
Ответы
Ответ 1
Обновление: теперь это доступно в R 3.0.2.
В своем недавнем коммите Пол Муррелл добавил новый параметр только для чтения в par()
с именем page
, который дает TRUE
или FALSE
, указывая, должен ли следующий график открывать новую страницу.
Это было достигнуто путем копирования некоторого кода из GNewPlot()
и доступно только в R-devel в данный момент.
Ответ 2
От ?par
:
‘mfg’ A numerical vector of the form ‘c(i, j)’ where ‘i’ and ‘j’
indicate which figure in an array of figures is to be drawn
next (if setting) or is being drawn (if enquiring). The
array must already have been set by ‘mfcol’ or ‘mfrow’.
Итак, кажется, что вам нужно будет использовать функция сопряжения, чтобы назначить уникальный идентификатор начальному значение par("mfg")[1:2]
, а затем проверить следующие значения par("mfg")[1:2]
на этот ключ. Например, допустимый парирование будет 2**par("mfg")[1] * 3**par("mfg")[2]
:
Pid <- function(ij, test.id=NA){
mi <- ij[1]
mj <- ij[2]
ijd <- 2**mi * 3**mj
if (!is.na(test.id)) ijd <- ijd == test.id
return(ijd)
}
Вернемся к вашему примеру:
layout(matrix(c(1,3,2,3), 2))
x0 <- par("mfg") # 2 1 2 2
id <- Pid(x0) # 12
plot(rnorm(10))
x1 <- par("mfg")
p1 <- Pid(x1, id) # FALSE (layout is not full)
plot(rnorm(10))
x2 <- par("mfg")
p2 <- Pid(x2, id) # FALSE (layout is not full)
plot(rnorm(10))
x3 <- par("mfg")
p3 <- Pid(x3, id) # TRUE (layout is now full)
#
rbind(p1,p2,p3)
# [,1]
#p1 FALSE
#p2 FALSE
#p3 TRUE
Я полагаю, однако, что без начального id
вам не повезло.