0

I do not understand how to handle objects, stored in a data.frame, in certain lattice plots. In the second plot I get the error msg bellow. Is it possible to get it to work?

require(lattice)
require(latticeExtra)
data<-data.frame(a=I(list(1,2,3)),b=factor(1:3))
ecdfplot(~a|b,data=data
             ,layout=c(1,3)              
             ,panel=function(x,...){
                print(x[[1]])
                panel.xyplot(x[[1]],.5,col=2)
              }
         )
 data<-data.frame(a=I(list(diag(1,2,2),diag(1,2,2),diag(1,2,2))),b=factor(1:3))
 ecdfplot(~a|b,data=data
         ,layout=c(1,3)              
         ,panel=function(x,...){
            print(x[[1]][1,1])
            panel.xyplot(x[[1]][1,1],.5,col=2)
          }
     )


Error in prepanel.default.function(darg = list(give.Rkern = FALSE, n = 50,  : 
 (list) object cannot be coerced to type 'double'
agstudy
  • 119,832
  • 17
  • 199
  • 261
Klaus
  • 1,946
  • 3
  • 19
  • 34

2 Answers2

1

convert x to a numeric correct the problem

    x <- x[[1]]
    panel.xyplot(as.numeric(x),.5,col=2)
karthikr
  • 97,368
  • 26
  • 197
  • 188
agstudy
  • 119,832
  • 17
  • 199
  • 261
  • sry I cant see what you mean. The error msg comes from the snd plot, how I mentioned. I tried your hint for it, but there are no differences. – Klaus Dec 15 '12 at 13:15
  • currently I try to prevent the error msg by defining a own prepanel function but it seems to it will not help. – Klaus Dec 15 '12 at 15:14
1

From ?ecdfplot:

For the "formula" method, x is a formula describing the form of conditioning plot, and has to be of the form ~x, where x is assumed to be a numeric vector.

If x (in your case the variable a) is not numeric, it gets coerced via as.numeric at many points along the road to getting plotted. One of those points is in the prepanel function.

In your first data object, data$a can be coerced without an error to a numeric (double) vector. In your second data object, data$a cannot be successfully coerced.

> as.numeric(data$a)
Error: (list) object cannot be coerced to type 'double'

Even though you specify a panel function that should work, the prepanel function will throw an error.


UPDATE after clarification:

There is a way to pass arbitrary objects to the panel function, and this is done by passing an argument via the ellipses of ecdfplot. The argument must be named in a way that it does not match any named argument in the normal lattice function (and it's best to avoid any named argument in the panel functions used). Furthermore, the formula argument to x in ecdfplot must also represent data that the ecdfplot function can handle, i.e., not a list, as explained above.

In the example below, I pass the data.frame data4 twice to the plot function: once as the argument data and once via the ellipses as the argument plotData. This will pass the whole data.frame to the panel function, and it is thus necessary to pass the subscripts to the panel function as well, so that the appropriate data can be subscripted.

# New example data
data4 <- data.frame(a = 0:2, b = factor(1:3),
  forPrint = letters[1:3],
  forXyplot = I(list(list(x = seq(0, 1, .25), y = rev(seq(0, 1, .25))),
  list(x = seq(0, 1, .5), y = rev(seq(0, 1, .5))), list(x = seq(0, 1, .2),
  y = rev(seq(0, 1, .2))))))

> data4
  a b forPrint    forXyplot
1 0 1        a c(0, 0.2....
2 1 2        b c(0, 0.5....
3 2 3        c c(0, 0.2....

ecdfplot(~ a|b, data = data4
         ,layout=c(1,3)              
         ,panel=function(x, subscripts = subscripts, ...){
            # plotData is passed to the panel function via the ellipses,
            # so extract those arguments vial match.call
            args <- match.call(expand.dots = FALSE)$...
            # Print the column forPrint
            print(args$plotData$forPrint[subscripts])
            # Plot the forXyplot column using do.call, since the column is
            # a list with x and y items.
            do.call(panel.xyplot, c(args$plotData[subscripts, "forXyplot"][[1]],
              col=2))
          }
          ,plotData = data4
     )

You'll notice from the plot that the x-axis limits cover the range of a and extend beyond the range of the plotted values. Of course, one could correct this by using a custom prepanel function.

BenBarnes
  • 19,114
  • 6
  • 56
  • 74
  • `it would be best to organize your data frame in an appropriate way before plotting` that is my only solution for now. But the data are organized as objects with certain parameters. It would be less code if I could extract the plotting data and specific parameters from certain objects giving through the panel.function. `In full generality, the return value of prepanel can be a list consisting of components xlim, ylim, xat, yat, dx, and dy.` I try to do so, but I dont get a working example. – Klaus Dec 16 '12 at 12:57
  • @Klaus, ah, now I see what you're trying to do (I think). However, the default `prepanel` function is still being called. I'm about to go out, but I can take a further look at your question later. – BenBarnes Dec 16 '12 at 13:01
  • @Klaus, after further pondering, I'm not sure exactly what your goal is. Perhaps if you could expand your question with exactly what it is you'd like to accomplish? – BenBarnes Dec 16 '12 at 16:35
  • imagine you would use arbitrary objects in place of diagonal matrices in the snd data.frame above. In detail, every object contains numeric vectors x and y, which should passed to the panel.xyplot function and a character vector for a label. It would be nice, if I dont have to rebuild the data for ecdfplot function. So if I could extract the x,y vectors from my objects inside the panel function I have also access tothe specific label of these data. – Klaus Dec 16 '12 at 17:28
  • @Klaus, please see the update. If that doesn't give you an idea of what to do, please consider editing your original post to provide more details. – BenBarnes Dec 16 '12 at 19:47
  • Thx, I was also thinking about that before. A question to your code: is there a reason to use match.call instead of `args<-list(...)` or `panel=function(x, plotData, subscripts = subscripts, ...)`? – Klaus Dec 16 '12 at 21:44
  • @Klaus, I've seen `match.call` used this way before, but there's probably not much difference using `list(...)` in this case. As to having `plotData` as a formal argument to the panel function, that might get unwieldy if you pass many objects this way. At the moment, though, I can't think of any reason to completely reject any of those methods. – BenBarnes Dec 16 '12 at 22:12