Ti Litt
Ti Litt

Reputation: 53

Using an ifelse or if loop in the panel function in Lattice doesn't work with panel.xyplot

I'm trying to draw a plot with lattice in which both the point colours and shape change based on variables in the data. This works fine when I set the col and pch values on their own, and don't put panel.xyplot in the ifelse statement:

#Setup
library(cluster)
library(lattice)

xyplot(V8 ~ V7,
       data = flower,
       V8_var = flower$V8,
       panel = function(x, y, ..., V8_var, subscripts) {
         
         col <- ifelse(V8_var[subscripts] < 50,
                       'blue',
                       'orange')
         
         pch <- ifelse(V8_var[subscripts] < 50,
                       2,
                       6)
         
           panel.xyplot(x,y,type='p',
                        col = col,
                        pch = pch)
         
       })

The 'correct' image drawn with two different colours and two different shapes

However this does not work when I use panel.xyplot in an ifelse or if loop:

xyplot(V8 ~ V7,
       data = flower,
       V8_var = flower$V8,
       panel = function(x, y, ..., V8_var, subscripts) {
         
         col <- ifelse(V8_var[subscripts] < 50,
                       'blue',
                       'orange')
         ifelse(
           V8_var[subscripts] < 50,
           panel.xyplot(x,y,type='p',
                        col = col,
                        pch = 2),
           panel.xyplot(x,y,type='p',
                        col = col,
                        pch = 6)
         )
         
       })

Graph with two colours of points but only one pch even though the panel function had an ifelse statement which called panel.xyplot with a different pch value depending on the value of the variable V8. Also gives the error message: "Error using packet 1 replacement has length zero".

xyplot(V8 ~ V7,
       data = flower,
       V8_var = flower$V8,
       panel = function(x, y, ..., V8_var, subscripts) {
         
         col <- ifelse(V8_var[subscripts] < 50,
                       'blue',
                       'orange')
         
         if(V8_var[subscripts] < 50){
           panel.xyplot(x,y,type='p',
                        col = col,
                        pch = 2)
           } else {
           panel.xyplot(x,y,type='p',
                        col = col,
                        pch = 6)
           }
       }) 

Graph with two colours of points but only one pch even though the panel function had an if loop which called panel.xyplot with a different pch value depending on the value of the variable V8.

Using the if statement also gives the warning:

Warning message:
In if (V8_var[subscripts] < 50) { :
  the condition has length > 1 and only the first element will be used

The way around this is to get the variable values through an if or ifelse statement and then plug those into panel.xyplot outside of any if statements, but I do not understand why the ifelse statement doesn't work as I expect when panel.xyplot is within it?

SessionInfo:

R version 4.0.2 (2020-06-22)
Platform: x86_64-apple-darwin17.0 (64-bit)
Running under: macOS Mojave 10.14.6

Matrix products: default
BLAS:   /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/4.0/Resources/lib/libRlapack.dylib

locale:
[1] en_GB.UTF-8/en_GB.UTF-8/en_GB.UTF-8/C/en_GB.UTF-8/en_GB.UTF-8

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] lattice_0.20-41 cluster_2.1.0  

loaded via a namespace (and not attached):
[1] compiler_4.0.2 tools_4.0.2    grid_4.0.2 

Upvotes: 0

Views: 97

Answers (1)

G. Grothendieck
G. Grothendieck

Reputation: 269371

panel.xyplot cannot be an argument of ifelse. Calculate pch in the same way that the code calculated col:

library(cluster)
library(lattice)
xyplot(V8 ~ V7,
       data = flower,
       V8_var = flower$V8,
       panel = function(x, y, ..., V8_var, subscripts) {
         
         col <- ifelse(V8_var[subscripts] < 50, 'blue', 'orange')
         pch <- ifelse(V8_var[subscripts] < 50, 2, 6)
         panel.xyplot(x,y,type='p',
                        col = col,
                        pch = pch)
         
       })

although in this case you don't even need a panel function:

xyplot(V8 ~ V7,
       data = flower,
       col = ifelse(flower$V8 < 50, "blue", "orange"),
       pch = ifelse(flower$V8 < 50, 2, 6))

Upvotes: 1

Related Questions