Jenny Bryan
2007-Mar-22 22:08 UTC
[R] unexpected behavior of trellis calls inside a user-defined function
I am making a battery of levelplots and wireframes for several fitted models. I wrote a function that takes the fitted model object as the sole argument and produces these plots. Various strange behavior ensued, but I have identified one very concrete issue (illustrated below): when my figure-drawing function includes the addition of points/lines to trellis plots, some of the information (main title, placement of additional points) from my i-th function call is leaking over into the i+1-th call. In the example below, I just get unexpected results. In my actual application, it breaks the whole function and one of the error messages I've gotten is: > figFun(smoothFit1) ## no longer worked, once I got fancy with trellis Error in depth(path) : no applicable method for "depth" Smallest example I could construct to illustrate at least one of my problems: predVals <- expand.grid(list(Sepal.Length = seq(from = min(iris$Sepal.Length), to = max(iris$Sepal.Length), length = 50), Petal.Length = seq(from = min(iris$Petal.Length), to = max(iris$Petal.Length), length = 50))) irisFit <- lm(Sepal.Width ~ Sepal.Length * Petal.Length, data = iris) predSurf <- data.frame(predVals, Sepal.Width = predict(irisFit, predVals)) trellis.device("X11",width = 8, height = 8) levelplot(Sepal.Width ~ Sepal.Length * Petal.Length, predSurf, main = "Produced at command line, Take 1") # put levelplot call inside a function myFunction <- function(surf) { levelplot(Sepal.Width ~ Sepal.Length * Petal.Length,surf, main = "Produced by function, Take 1") } myFunction(predSurf) # OK, get the expected figure result ## now .. what if we add points to the plot? levelplot(Sepal.Width ~ Sepal.Length * Petal.Length, predSurf, main = "Produced at command line, Take 2") trellis.focus("panel", 1, 1) # address the correct part of the figure lpoints(6,4,pch = 19, cex = 2) # a point appears in correct location # I get what I expect ## any crosstalk from adjacent command line invocations? no levelplot(Sepal.Width ~ Sepal.Length * Petal.Length, predSurf, main = "Produced at command line, Take 3") trellis.focus("panel", 1, 1) # address the correct part of the figure lpoints(5,2,pch = 19, cex = 2) # a point appears in correct location # I get what I expect # put all this inside a function myFunction <- function(surf) { levelplot(Sepal.Width ~ Sepal.Length * Petal.Length,surf, main = "Produced by function, Take 2") trellis.focus("panel", 1, 1) # address the correct part of the lpoints(7,5,pch = 19, cex = 2) # a point appears in correct location } myFunction(predSurf) # the title still says "Produced at command line, Take 3" # and points appear at (5,2) AND (7,5) ... why?
Deepayan Sarkar
2007-Mar-22 22:20 UTC
[R] Fwd: unexpected behavior of trellis calls inside a user-defined function
Forgot to CC. ---------- Forwarded message ---------- From: Deepayan Sarkar <deepayan.sarkar at gmail.com> Date: Mar 22, 2007 3:19 PM Subject: Re: [R] unexpected behavior of trellis calls inside a user-defined function To: Jenny Bryan <jenny at stat.ubc.ca> Hi, I see lots of calls to trellis.focus(), but none to trellis.unfocus(). trellis.focus() sets the ``viewport'' to a particular panel. Unless you go back to the root viewport, you will get stuck in a weird place in the viewport tree. This is not a problem if your next plot is on a new page, but will be otherwise. So short anwser: call trellis.unfocus() when you are done doing whatever you need to do after a trellis.focus() call. Deepayan On 3/22/07, Jenny Bryan <jenny at stat.ubc.ca> wrote:> I am making a battery of levelplots and wireframes for several fitted > models. I wrote a function that takes the fitted model object as the > sole argument and produces these plots. Various strange behavior > ensued, but I have identified one very concrete issue (illustrated > below): when my figure-drawing function includes the addition of > points/lines to trellis plots, some of the information (main title, > placement of additional points) from my i-th function call is leaking > over into the i+1-th call. In the example below, I just get > unexpected results. In my actual application, it breaks the whole > function and one of the error messages I've gotten is: > > > figFun(smoothFit1) ## no longer worked, once I got fancy with trellis > Error in depth(path) : no applicable method for "depth" > > Smallest example I could construct to illustrate at least one of my > problems: > > predVals <- > expand.grid(list(Sepal.Length = seq(from = min(iris$Sepal.Length), > to = max(iris$Sepal.Length), length = 50), > Petal.Length = seq(from = min(iris$Petal.Length), > to = max(iris$Petal.Length), length = 50))) > irisFit <- lm(Sepal.Width ~ Sepal.Length * Petal.Length, data = iris) > predSurf <- data.frame(predVals, Sepal.Width = predict(irisFit, > predVals)) > trellis.device("X11",width = 8, height = 8) > > levelplot(Sepal.Width ~ Sepal.Length * Petal.Length, > predSurf, main = "Produced at command line, Take 1") > > # put levelplot call inside a function > myFunction <- function(surf) { > levelplot(Sepal.Width ~ Sepal.Length * Petal.Length,surf, > main = "Produced by function, Take 1") > } > myFunction(predSurf) > # OK, get the expected figure result > > ## now .. what if we add points to the plot? > levelplot(Sepal.Width ~ Sepal.Length * Petal.Length, > predSurf, main = "Produced at command line, Take 2") > trellis.focus("panel", 1, 1) # address the correct part of the > figure > lpoints(6,4,pch = 19, cex = 2) # a point appears in correct location > # I get what I expect > > ## any crosstalk from adjacent command line invocations? no > levelplot(Sepal.Width ~ Sepal.Length * Petal.Length, > predSurf, main = "Produced at command line, Take 3") > trellis.focus("panel", 1, 1) # address the correct part of the > figure > lpoints(5,2,pch = 19, cex = 2) # a point appears in correct location > # I get what I expect > > # put all this inside a function > myFunction <- function(surf) { > levelplot(Sepal.Width ~ Sepal.Length * Petal.Length,surf, > main = "Produced by function, Take 2") > trellis.focus("panel", 1, 1) # address the correct part of the > lpoints(7,5,pch = 19, cex = 2) # a point appears in correct location > } > myFunction(predSurf) > # the title still says "Produced at command line, Take 3" > # and points appear at (5,2) AND (7,5) ... why? > > ______________________________________________ > R-help at stat.math.ethz.ch mailing list > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code. >
Jenny Bryan
2007-Mar-23 03:45 UTC
[R] unexpected behavior of trellis calls inside a user-defined function
I got 2 helpful responses (from Deepayan, cc'ed to the list, and Sundar Dorai-Rah, directly to me). Sundar pointed out something from the FAQ: inside a function, one must explicitly print lattice/ trellis graph object. It turns out that, at least in the small example I gave, Sundar's tip was the one that fixed it. The combination of both fixes got my original, more complicated function working. Thanks, Jenny * follow trellis.focus() calls with trellis.unfocus() * use print(levelplot(...)) inside a function On 22-Mar-07, at 3:08 PM, Jenny Bryan wrote:> I am making a battery of levelplots and wireframes for several > fitted models. I wrote a function that takes the fitted model > object as the sole argument and produces these plots. Various > strange behavior ensued, but I have identified one very concrete > issue (illustrated below): when my figure-drawing function includes > the addition of points/lines to trellis plots, some of the > information (main title, placement of additional points) from my i- > th function call is leaking over into the i+1-th call. In the > example below, I just get unexpected results. In my actual > application, it breaks the whole function and one of the error > messages I've gotten is: > > > figFun(smoothFit1) ## no longer worked, once I got fancy with > trellis > Error in depth(path) : no applicable method for "depth" > > Smallest example I could construct to illustrate at least one of my > problems: > > predVals <- > expand.grid(list(Sepal.Length = seq(from = min(iris$Sepal.Length), > to = max(iris$Sepal.Length), length = 50), > Petal.Length = seq(from = min(iris$Petal.Length), > to = max(iris$Petal.Length), length = 50))) > irisFit <- lm(Sepal.Width ~ Sepal.Length * Petal.Length, data = iris) > predSurf <- data.frame(predVals, Sepal.Width = predict(irisFit, > predVals)) > trellis.device("X11",width = 8, height = 8) > > levelplot(Sepal.Width ~ Sepal.Length * Petal.Length, > predSurf, main = "Produced at command line, Take 1") > > # put levelplot call inside a function > myFunction <- function(surf) { > levelplot(Sepal.Width ~ Sepal.Length * Petal.Length,surf, > main = "Produced by function, Take 1") > } > myFunction(predSurf) > # OK, get the expected figure result > > ## now .. what if we add points to the plot? > levelplot(Sepal.Width ~ Sepal.Length * Petal.Length, > predSurf, main = "Produced at command line, Take 2") > trellis.focus("panel", 1, 1) # address the correct part of the > figure > lpoints(6,4,pch = 19, cex = 2) # a point appears in correct location > # I get what I expect > > ## any crosstalk from adjacent command line invocations? no > levelplot(Sepal.Width ~ Sepal.Length * Petal.Length, > predSurf, main = "Produced at command line, Take 3") > trellis.focus("panel", 1, 1) # address the correct part of the > figure > lpoints(5,2,pch = 19, cex = 2) # a point appears in correct location > # I get what I expect > > # put all this inside a function > myFunction <- function(surf) { > levelplot(Sepal.Width ~ Sepal.Length * Petal.Length,surf, > main = "Produced by function, Take 2") > trellis.focus("panel", 1, 1) # address the correct part of the > lpoints(7,5,pch = 19, cex = 2) # a point appears in correct location > } > myFunction(predSurf) > # the title still says "Produced at command line, Take 3" > # and points appear at (5,2) AND (7,5) ... why? > > >