2013-08-06 19 views
18

Aktualizacja: Poprosiłem Paul Murrell (dalej „bossa”), a on powiedział mi, że decyzję o otwarciu nowej strony jest wykonany w src/library/graphics/src/graphics.c przez GNewPlot:Jak sprawdzić, czy działka jest kompletny lub nie

pGEDevDesc GNewPlot(Rboolean recording) 

Skutecznie sprawdza, czy par(mfg) i par(new) decydują, czy otworzyć nową stronę. Jak wykonać ten test w pakiecie dodatków?

Rozwiązanie z użyciem czystego kodu R lub kodu C jest dopuszczalne.


knitr wykorzystuje pakiet evaluate do oceny fragmentów kodu R i wyniki przechwytywania, w tym działek. Krótko mówiąc, evaluate wywołuje recordPlot(), aby zarejestrować migawkę bieżącego wykresu po wyliczeniu każdego wyrażenia kodu, a także gdy wywołania haczyków takie jak before.plot.new i before.grid.newpage są wywoływane (zwykle dzieje się to przed narysowaniem nowego wykresu). Dla tych "Luke'a", proszę use the source, jeśli to nie jest wystarczająco jasne.

Po utworzeniu migawki musimy zdecydować, czy ją zachować, ponieważ migawka może nie zostać zmieniona po ocenie nowego wyrażenia, które nie ma związku z wykreślaniem. Teraz przychodzi mój problem: jeśli wykres zawiera sub-działki (na przykład pairs(), coplot() lub par(mfrow = c(2, 3)) w grafice bazowej R), nie powinniśmy przechowywać niekompletnych migawek. W poniższym przykładzie, pierwsze trzy działki należy wyrzucić:

par(mfrow = c(2, 2)) 
plot(rnorm(10)) 
plot(rnorm(10)) 
plot(rnorm(10)) 
plot(rnorm(10)) 

Aby to osiągnąć, możemy porównać par("mfg")[1:2] do par("mfg")[3:4] (jak widać w kodzie źródłowym), i to działa dobrze w niektórych przypadkach, ale nie wszystko, na przykład, issue #25:

layout(matrix(c(1,3,2,3), 2)) 
plot(rnorm(10)) 
plot(rnorm(10)) 
plot(rnorm(10)) 

teraz jak mam wiedzieć, fabuła nie jest zakończona przed linią 4? Sztuczka mfg już nie działa.

Szukałem odpowiedzi na ten problem przez długi czas i będę naprawdę wdzięczny, jeśli ktoś może dać mi wskazówkę; dalsze szczegóły znajdują się w dwóch powyższych linkach i mogę wyjaśnić, czy coś jest niejasne. Uważam, że musi istnieć rozwiązanie, ponieważ wszystkie urządzenia R wiedzą, kiedy rozpocząć nowy ekran lub plik wydruku, a niekompletne wykresy nie uruchamiają nowych ekranów lub plików wydruku.

+0

Naprawdę uważam, że nie da się określić, czy fabuła jest kompletna i nie będzie późniejszego wyrażenia R, które rozszerzyłoby to dalej. To, co zrobiłem w [pander] (http://rapporter.github.io/pander) z funkcją 'evals' (której używam zamiast' assess' dla jakiegoś dodatkowego), to że użytkownik może "oznaczyć" linię z wiodącym znakiem '+', który ma być zawarty w ostatniej nazwie działki - to naprawdę nieoptymalne rozwiązanie, ale nie mogłem wymyślić lepszego pomysłu. Więcej szczegółów: http://support.rapporter.net/entries/22485898-How-to-evaluate-multiple-commands-together – daroczig

+0

Definiowanie layoutu niekoniecznie oznacza, że ​​wszystkie komórki będą w końcu używane, czy nie ? Mogę sobie wyobrazić sytuacje, w których jedna cela jest celowo pusta. Nie byłoby potrzeby "dev.off()", jeśli istnieje określona odpowiedź, myślę. – baptiste

+0

@daroczig dzięki! Myślę, że to jest rzeczywiście nieoptymalne; @ Baptiste masz rację; można "dev.off()" zanim wszystkie komórki zostaną wypełnione, i to nie jest dla mnie problemem –

Odpowiedz

5

Aktualizacja: jest już dostępna w wersji 3.0.2.


w Jego recent commit Paweł Murrell dodano nowy parametr tylko do odczytu w par() nazwie page, co daje TRUE lub FALSE, ze wskazaniem, czy kolejna działka musi otworzyć nową stronę.

Zostało to osiągnięte poprzez skopiowanie kodu z GNewPlot() i jest obecnie dostępne tylko w wersji R.

+1

To jest już dostępne w wersji 3.0.2 –

4

Od ?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’. 

Więc wydaje się, że trzeba by użyć pairing function przypisać niepowtarzalny identyfikator do wartości początkowej par("mfg")[1:2], a następnie testować kolejne wartości par("mfg")[1:2] przeciwko temu kluczowi. Ważny paring, na przykład, byłoby 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) 
} 

Powrót do przykładu:

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 

Przypuszczam jednak, że bez początkowego id, byłbyś pecha.

+0

dzięki! dałeś mi dobrą inspirację! funkcja parowania nie jest tutaj krytyczna; to jest początkowe 'mfg', które jest naprawdę ważne; Mogę po prostu użyć 'identycznego()', aby porównać kolejne wartości 'mfg' z początkowym wektorem, i ja to zrobiłem (https://github.com/hadley/evaluate/commit/5f1ca6b5e9b19fc734e0792d9a65334637b3a013), ale wciąż robię nie sądzę, że jest to niezawodne podejście –

Powiązane problemy