简体   繁体   中英

Arbitrary objects as argument for lattice functions

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'

convert x to a numeric correct the problem

    x <- x[[1]]
    panel.xyplot(as.numeric(x),.5,col=2)

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, ie, 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM