2013-03-04 4 views
7

Rs Plotting ist ideal für die Datensuche, da es oft sehr intelligente Standardwerte hat. Wenn Sie beispielsweise mit einer Formel zeichnen, werden die Beschriftungen für die Zeichenachsen aus der Formel abgeleitet. Mit anderen Worten erzeugen die folgenden zwei Anrufe die gleiche Ausgabe:Wie kann ich ein Diagramm mit dem R-Aufruf, der es erzeugt hat, automatisch benennen?

plot(x~y) 
plot(x~y, xlab="x", ylab="y") 

Gibt es eine Möglichkeit, einen ähnlichen „intelligenten Auto-Titel“ zu bekommen?

Zum Beispiel würde Ich mag

plot(x~y, main=<something>) 

anrufen und die gleiche Leistung wie der Aufruf

plot(x~y, main="plot(x~y)") 

produzieren Wenn die <something> der Anruf Einsätze verwendet eine Art von Selbstbeobachtung verwendet wird.

Gibt es eine Möglichkeit, dies in R zu tun, entweder durch einen Standardmechanismus oder ein externes Paket?

edit: Ein Vorschlag bestand darin, die Formel als String anzugeben und diesen als Argument an einen formula() Aufruf sowie main zu übergeben. Dies ist nützlich, aber es fehlen Parameter, die sich auf einen Plot auswirken können, z. B. die Verwendung von Teilmengen von Daten. Um dies näher auszuführen, würde ich

x<-c(1,2,3) 
y<-c(1,2,3) 
z<-c(0,0,1) 
d<-data.frame(x,y,z) 
plot(x~y, subset(d, z==0), main=<something>) 

Um die gleiche Wirkung haben wie

plot(x~y, subset(d, z==0), main="plot(x~y, subset(d, z==0))") 

Antwort

7

Ich glaube nicht, das eine dünne Hülle getan werden kann, um ohne das Schreiben plot(). Der Grund dafür ist, dass R "Ausgelieferte Argumente" im Auswertungsrahmen der aufrufenden Funktion auswertet, in der auf den aktuellen Funktionsaufruf (see here for details) nicht zugegriffen werden kann.

Im Auswertungsrahmen der Funktion werden dagegen "Standardargumente" ausgewertet, von denen Introspektion möglich ist. Hier sind ein paar Möglichkeiten (die sich nur darin, ob Sie „MyPlot“ oder „Plot“ wollen im Titel erscheinen:

## Function that reports actual call to itself (i.e. 'myPlot()') in plot title. 
myPlot <- function(x,...) { 
    cl <- deparse(sys.call()) 
    plot(x, main=cl, ...) 
} 

## Function that 'lies' and says that plot() (rather than myPlot2()) called it. 
myPlot2 <- function(x,...) { 
    cl <- sys.call() 
    cl[[1]] <- as.symbol("plot") 
    cl <- deparse(cl) 
    plot(x, main=cl, ...) 
} 

## Try them out 
x <- 1:10 
y <- 1:10 
par(mfcol=c(1,2)) 
myPlot(x,y) 
myPlot2(y~x) 

Hier ist eine allgemeine Lösung:

plotCaller <- function(plotCall, ...) { 
    main <- deparse(substitute(plotCall)) 
    main <- paste(main, collapse="\n") 
    eval(as.call(c(as.list(substitute(plotCall)), main=main, ...))) 
} 

## Try _it_ out 

plotCaller(hist(rnorm(9999), breaks=100, col="red")) 

library(lattice) 
plotCaller(xyplot(rnorm(10)~1:10, pch=16)) 

## plotCaller will also pass through additional arguments, so they take effect 
## without being displayed 
plotCaller(xyplot(rnorm(10)~1:10), pch=16) 

Deparse wird versuchen, break deparsed Zeilen, wenn sie zu lang werden (der Standardwert ist 60 Zeichen). Wenn es dies tut, gibt es einen Vektor von Zeichenfolgen. Plot Methoden nehmen an, dass 'Main' ist eine einzelne Zeichenfolge, so dass die Zeile main <- paste(main, collapse='\n') dies durch Verkettung behandelt die Zeichenfolgen, die von deeparse zurückgegeben werden, verbinden sie unter Verwendung \n.

Hier ist ein Beispiel, wo dies notwendig ist:

plotCaller(hist(rnorm(9999), breaks=100, col="red", xlab="a rather long label", 
    ylab="yet another long label")) 
+0

Brilliant! Ich denke, die allgemeinere Lösung löst das Problem recht gut. Es ist im Grunde das gleiche wie Greg Snows myplot2, aber ich habe dieses hier gewählt, da ich denke, dass es einfacher ist zu verstehen, wie es funktioniert. – saffsd

+0

@saffsd - Coole Ideen in den Änderungen, die Sie gemacht haben. Vielen Dank! Würdest du bitte ein Beispiel hinzufügen, das zeigt, wo die Paste (main, collapse = "\ n") ins Spiel kommen könnte? –

3

Natürlich mag es! Hier gehen ya:

x = rnorm(100) 
y = sin(x) 

something = "y~x" 

plot(formula(something),main=something) 

enter image description here

+1

Ist 'paste' wirklich notwendig? – joran

+0

Sie können es bearbeiten, um genau das zu bekommen, was Sie wollen, aber Sie bekommen die Idee. –

+0

Sie können es ohne die Paste tun. –

3

Sie könnten von der Funktionalität von match.call denken. Dies funktioniert jedoch nur, wenn es innerhalb einer Funktion aufgerufen wird und nicht als Argument übergeben wird.Sie könnten Ihre Wrapper-Funktion erstellen, die match.call dann passieren alles andere auf plot oder verwenden Ersatz den Anruf es erfassen dann ändern mit dem Aufruf aufrufen würde, bevor die Bewertung:

x <- runif(25) 
y <- rnorm(25, x, .1) 

myplot <- function(...) { 
    tmp <- match.call() 
    plot(..., main=deparse(tmp)) 
} 

myplot(y~x) 
myplot(y~x, xlim=c(-.25,1.25)) 

## or 

myplot2 <- function(FUN) { 
    tmp1 <- substitute(FUN) 
    tmp2 <- deparse(tmp1) 
    tmp3 <- as.list(tmp1) 
    tmp4 <- as.call(c(tmp3, main=tmp2)) 
    eval(tmp4) 
} 

myplot2(plot(y~x)) 
myplot2(plot(y~x, xlim=c(-.25,1.25))) 
Verwandte Themen