Search code examples
rplotpanellattice

R lattice correctly labelling points with xyplot


library(lattice)

# load reproducible data set
attach(mtcars)

# change the rownames into a column value and remove the rownames
mtcars <- as.data.frame(cbind(car.name=rownames(mtcars), mtcars))
rownames(mtcars) <- NULL

# panel function parameters so that I label the points that are 100 units
# different between the hp and disp values and label the points with the car name

panel = function (x, y, ...) {
    panel.xyplot(x, y, ...)
    x1 <- x[x-y > 100 | y-x > 100]
    y1 <- y[x-y > 100 | y-x > 100]
    panel.text(x1, y1, labels=mtcars$car.name, pos=3)   
}

#calling the xyplot
xyplot(hp~disp, data=mtcars, main=NULL, ylab="hp", xlab="disp", 
       jitter=TRUE, pch=1, as.table=TRUE, panel=panel)

xyplot of mtcars

I can see that all points which show a difference of 100 units between hp and disp have a label. However, the label does not match the actual data in the table. I can tell this by first sorting mtcars by the column disp in descending order:

mtcars <- mtcars[order(-mtcars$disp),]
head(mtcars)
              car.name  mpg cyl disp  hp drat    wt  qsec vs am gear carb
15  Cadillac Fleetwood 10.4   8  472 205 2.93 5.250 17.98  0  0    3    4
16 Lincoln Continental 10.4   8  460 215 3.00 5.424 17.82  0  0    3    4
17   Chrysler Imperial 14.7   8  440 230 3.23 5.345 17.42  0  0    3    4
25    Pontiac Firebird 19.2   8  400 175 3.08 3.845 17.05  0  0    3    2
5    Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
7           Duster 360 14.3   8  360 245 3.21 3.570 15.84  0  0    3    4

            
    

As you can see the car.name with the highest disp is the Cadillac Fleetwood and this is not labelled in the graph, in fact another car name appears.

How can I have the correct car name displayed according to my condition that only cars with >100 units difference between disp and hp are labelled? Something is wrong with my panel function.


Solution

  • x1, y1 and mtcars$carname have different lengths, hence the labels do not correspond:

    length(x1)=11
    length(y1)=11,
    length(mtcars$carname)=32
    

    Here is a modified version:

    panel = function (x, y, ...) {
        panel.xyplot(x, y, ...)
        v <- abs(x - y) > 100
        panel.text(x[v], y[v], labels=mtcars$car.name[v], pos=3)
    }
    
    xyplot(hp~disp, data=mtcars, main=NULL, ylab="hp", xlab="disp", 
           jitter=TRUE, pch=1, as.table=TRUE, panel=panel)
    

    enter image description here