Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Draw a quadratic spline through points in lattice

Tags:

r

lattice

Based on this great question: How to draw a smooth curve passing through some points

How would one do this in lattice?

plot(rnorm(120), rnorm(120), col="darkblue", pch=16, xlim=c(-3,3), ylim=c(-4,4))
points(rnorm(120,-1,1), rnorm(120,2,1), col="darkred", pch=16)
points(c(-1,-1.5,-3), c(4,2,0), pch=3, cex=3)
xspline(c(-1,-1.5,-3), c(4,2,0), shape = -1)

Should look like that:

Here is similar data, formatted more appropriately for a lattice plot:

dat <- data.frame(x=c(rnorm(120), rnorm(120,-1,1)),
                  y=c(rnorm(120), rnorm(120,2,1)),
                  l=factor(rep(c('B','R'),each=120))
)
spl <- data.frame(x=c(-1,-1.5,-3), 
                  y=c(4,2,0)
)

And here is what the linked question gave, translated to lattice:

xyplot(y ~ x,
       data=dat,
       groups=l,
       col=c("darkblue", "darkred"),
       pch=16,
       panel = function(x, y, ...) {
         panel.xyplot(x=spl$x, y=spl$y, pch=3, cex=3)
         ## panel.spline(x=spl$x, y=spl$y)              ## Gives an error, need at least four 'x' values
         panel.superpose(x, y, ...,
                         panel.groups = function(x, y, ...) {
                           panel.xyplot(x, y, ...)
                         }
         )
       },
       xlim=c(-3,3), ylim=c(-4,4)
)

enter image description here

like image 678
Matthew Lundberg Avatar asked Jan 13 '13 15:01

Matthew Lundberg


2 Answers

Here's a line-for line 'translation' of the base graphics solution into lattice. (The directness of the translation is made possible by the + operator supplied by the latticeExtra package. See ?layer for details of its usage.)

The final line invokes grid.xspline(), an exact grid analogue of the base graphic function xspline().

library(lattice)
library(grid)
library(latticeExtra)

xyplot(rnorm(120)~rnorm(120), pch=16, col="darkblue", 
       xlim = c(-3.1, 3.1), ylim = c(-4.1, 4.1)) +
xyplot(rnorm(120,2,1) ~ rnorm(120,-1,1), pch=16, col="darkred") +
xyplot(c(4,2,0) ~ c(-1,-1.5,-3), pch=3, cex=3) +
layer(grid.xspline(c(-1,-1.5,-3), c(4,2,0), shape = -1, default.units="native"))

(One peculiar detail of grid does pop up in the final line above: like several other of its low-level line-drawing functions, grid.xspline() defaults to "npc" units instead of the usually-desired "native" units used as defaults by grid.points() and many other grid.*() functions. Obviously that's easy enough to change --- once you're aware of it!)

enter image description here

like image 94
Josh O'Brien Avatar answered Nov 15 '22 06:11

Josh O'Brien


This is a little bit tricky but works.

plot(rnorm(120), rnorm(120), col="darkblue", pch=16, xlim=c(-3,3), ylim=c(-4,4))
points(rnorm(120,-1,1), rnorm(120,2,1), col="darkred", pch=16)
points(c(-1,-1.5,-3), c(4,2,0), pch=3, cex=3)

I use xspline without producing the draw

dd <- xspline(c(-1,-1.5,-3), c(4,2,0), shape = -1,draw=FALSE)

Then I use the points produced witn panel.lines

library(lattice)
xyplot(y ~ x,
       data=dat,
       groups=l,
       col=c("darkblue", "darkred"),
       pch=16,
       panel = function(x, y, ...) {
         panel.xyplot(x=spl$x, y=spl$y, pch=3, cex=3)
         panel.lines(dd$x,dd$y)
         panel.superpose(x, y, ...,
                         panel.groups = function(x, y, ...) {
                           panel.xyplot(x, y, ...)
                         }
         )
       },
       xlim=c(-3,3), ylim=c(-4,4)
)

enter image description here

like image 3
agstudy Avatar answered Nov 15 '22 06:11

agstudy