Commit b7940cf6 authored by agebhard's avatar agebhard
Browse files

bugfixes/enhancements from Martin Maechler (thanks :-)

parent c1322d6b
Package: akima Package: akima
Version: 0.4-4 Version: 0.4-5
Date: 2005-07-21
Title: Interpolation of irregularly spaced data Title: Interpolation of irregularly spaced data
Author: Fortran code by H. Akima Author: Fortran code by H. Akima
R port by Albrecht Gebhardt <albrecht.gebhardt@uni-klu.ac.at> R port by Albrecht Gebhardt <albrecht.gebhardt@uni-klu.ac.at>
aspline function by Thomas Petzoldt <petzoldt@rcs.urz.tu-dresden.de> aspline function by Thomas Petzoldt <petzoldt@rcs.urz.tu-dresden.de>
enhancements and corrections by Martin Maechler <maechler@stat.math.ethz.ch>
Maintainer: Albrecht Gebhardt <albrecht.gebhardt@uni-klu.ac.at> Maintainer: Albrecht Gebhardt <albrecht.gebhardt@uni-klu.ac.at>
Description: Linear or cubic spline interpolation for irregular gridded data Description: Linear or cubic spline interpolation for irregular gridded data
License: Fortran code: ACM, free for non-commercial use, R functions GPL License: Fortran code: ACM, free for non-commercial use, R functions GPL
"interp"<-function(x, y, z, xo = seq(min(x), max(x), length = 40), interp <-
yo = seq(min(y), max(y), length = 40), function(x, y, z,
ncp = 0, extrap = FALSE, duplicate = "error", dupfun = NULL) xo = seq(min(x), max(x), length = 40),
yo = seq(min(y), max(y), length = 40), ncp = 0,
extrap = FALSE, duplicate = "error", dupfun = NULL)
{ {
if (ncp==0) if (ncp == 0)
# use the old version for linear interpolation ## use the old version for linear interpolation
interp.old(x, y, z, xo, yo, ncp, extrap, duplicate, dupfun) interp.old(x, y, z, xo = xo, yo = yo, ncp = ncp,
else extrap = extrap, duplicate = duplicate, dupfun = dupfun)
interp.new(x, y, z, xo, yo, ncp, extrap, duplicate, dupfun) else ## use the new one
interp.new(x, y, z, xo = xo, yo = yo, linear = FALSE,
ncp = NULL,# not using 'ncp' argument
extrap = extrap, duplicate = duplicate, dupfun = dupfun)
} }
"interp.new"<-function(x, y, z, xo = seq(min(x), max(x), length = 40), interp.new <-
yo = seq(min(y), max(y), length = 40), linear=FALSE, function(x, y, z,
ncp = NULL, extrap = FALSE, duplicate = "error", xo = seq(min(x), max(x), length = 40),
dupfun = NULL) yo = seq(min(y), max(y), length = 40), linear = FALSE,
ncp = NULL, extrap = FALSE, duplicate = "error", dupfun = NULL)
{ {
if(!(all(is.finite(x)) && all(is.finite(y)) && all(is.finite(z)))) if(!(all(is.finite(x)) && all(is.finite(y)) && all(is.finite(z))))
stop("missing values and Infs not allowed") stop("missing values and Infs not allowed")
if(!is.null(ncp)){ if(!is.null(ncp)) {
if(ncp!=0){ if(ncp != 0) {
cat("ncp not supported, it is automatically choosen by Fortran code\n") cat("ncp not supported, it is automatically choosen by Fortran code\n")
} }
else { else {
...@@ -14,15 +15,15 @@ ...@@ -14,15 +15,15 @@
stop("use interp.old().") stop("use interp.old().")
} }
} }
if(linear){ if(linear) {
cat("linear interpolation not yet implemented with interp.new().\n") cat("linear interpolation not yet implemented with interp.new().\n")
stop("use interp.old().") stop("use interp.old().")
} }
drx <- diff(range(x)) drx <- diff(range(x))
dry <- diff(range(y)) dry <- diff(range(y))
if(drx == 0 || dry == 0) if(drx == 0 || dry == 0)
stop("all data collinear") # other cases caught in Fortran code stop("all data collinear") # other cases caught in Fortran code
if(drx/dry > 10000 || drx/dry < 0.0001) if(drx/dry > 10000 || drx/dry < 0.0001)
stop("scales of x and y are too dissimilar") stop("scales of x and y are too dissimilar")
n <- length(x) n <- length(x)
...@@ -30,48 +31,42 @@ ...@@ -30,48 +31,42 @@
ny <- length(yo) ny <- length(yo)
if(length(y) != n || length(z) != n) if(length(y) != n || length(z) != n)
stop("Lengths of x, y, and z do not match") stop("Lengths of x, y, and z do not match")
xy <- paste(x, y, sep =",")
i <- match(xy, xy) xy <- paste(x, y, sep = ",")# trick for 'duplicated' (x,y)-pairs
if(duplicate=="user" && !is.function(dupfun)) if(duplicate == "error") {
stop("duplicate=\"user\" requires dupfun to be set to a function") if(any(duplicated(xy)))
if(duplicate!="error") stop("duplicate data points: need to set 'duplicate = ..' ")
{ }
centre <- function(x) { else { ## duplicate != "error"
i <- match(xy, xy)
if(duplicate == "user")
dupfun <- match.fun(dupfun)#> error if it fails
ord <- !duplicated(xy)
if(duplicate != "strip") {
centre <- function(x)
switch(duplicate, switch(duplicate,
mean = mean(x), mean = mean(x),
median = median(x), median = median(x),
user = dupfun(x)) user = dupfun(x))
} z <- unlist(lapply(split(z,i), centre))
if(duplicate!="strip"){ } else {
z <- unlist(lapply(split(z,i), centre)) z <- z[ord]
ord <- !duplicated(xy)
x <- x[ord]
y <- y[ord]
n <- length(x)
}
else{
ord <- (hist(i,plot=FALSE,freq=TRUE,breaks=seq(0.5,max(i)+0.5,1))$counts==1)
x <- x[ord]
y <- y[ord]
z <- z[ord]
n <- length(x)
}
} }
else x <- x[ord]
if(any(duplicated(xy))) y <- y[ord]
stop("duplicate data points") n <- length(x)
}
zo <- matrix(0, nx, ny) zo <- matrix(0, nx, ny)
storage.mode(zo) <- "double" storage.mode(zo) <- "double"
miss <- !extrap #if not extrapolating use missing values miss <- !extrap # if not extrapolating, set missing values
extrap <- matrix(TRUE, nx, ny) misso <- matrix(TRUE, nx, ny)# hmm, or rather 'miss' ??
if(!is.null(ncp)){
if(extrap & ncp == 0) if(extrap && if(is.null(ncp)) linear else (ncp == 0))
warning("Cannot extrapolate with linear option")
}
else {
if(extrap & linear)
warning("Cannot extrapolate with linear option") warning("Cannot extrapolate with linear option")
}
ans <- .Fortran("sdsf3p", ans <- .Fortran("sdsf3p",
as.integer(1), as.integer(1),
as.integer(n), as.integer(n),
...@@ -86,13 +81,13 @@ ...@@ -86,13 +81,13 @@
ier = integer(1), ier = integer(1),
double(36 * n), double(36 * n),
integer(25 * n), integer(25 * n),
extrap = as.logical(extrap), extrap = as.logical(misso),
near = integer(n), near = integer(n),
nxt = integer(n), nxt = integer(n),
dist = double(n), dist = double(n),
PACKAGE = "akima") PACKAGE = "akima")[c("x", "y", "z", "extrap")]
temp <- ans[c("x", "y", "z", "extrap")]
if(miss) if(miss)
temp$z[temp$extrap]<-NA ans$z[ans$extrap] <- NA
temp[c("x", "y", "z")]
ans[c("x", "y", "z")]
} }
"interp.old"<-function(x, y, z, xo = seq(min(x), max(x), length = 40), "interp.old"<-function(x, y, z, xo = seq(min(x), max(x), length = 40),
yo = seq(min(y), max(y), length = 40), yo = seq(min(y), max(y), length = 40),
ncp = 0, extrap = FALSE, duplicate = "error", dupfun = NULL) ncp = 0, extrap = FALSE, duplicate = "error", dupfun = NULL)
{ {
if(!(all(is.finite(x)) && all(is.finite(y)) && all(is.finite(z)))) if(!(all(is.finite(x)) && all(is.finite(y)) && all(is.finite(z))))
stop("missing values and Infs not allowed") stop("missing values and Infs not allowed")
if(ncp>25){ if(ncp > 25) {
ncp <- 25 ncp <- 25
cat("ncp too large, using ncp=25\n") cat("ncp too large, using ncp=25\n")
} }
drx <- diff(range(x)) drx <- diff(range(x))
dry <- diff(range(y)) dry <- diff(range(y))
if(drx == 0 || dry == 0) if(drx == 0 || dry == 0)
...@@ -19,36 +20,34 @@ ...@@ -19,36 +20,34 @@
ny <- length(yo) ny <- length(yo)
if(length(y) != n || length(z) != n) if(length(y) != n || length(z) != n)
stop("Lengths of x, y, and z do not match") stop("Lengths of x, y, and z do not match")
xy <- paste(x, y, sep =",")
i <- match(xy, xy) xy <- paste(x, y, sep = ",")# trick for 'duplicated' (x,y)-pairs
if(duplicate=="user" && !is.function(dupfun)) if(duplicate == "error") {
stop("duplicate=\"user\" requires dupfun to be set to a function") if(any(duplicated(xy)))
if(duplicate!="error") stop("duplicate data points: need to set 'duplicate = ..' ")
{ }
centre <- function(x) { else { ## duplicate != "error"
i <- match(xy, xy)
if(duplicate == "user")
dupfun <- match.fun(dupfun)#> error if it fails
ord <- !duplicated(xy)
if(duplicate != "strip") {
centre <- function(x)
switch(duplicate, switch(duplicate,
mean = mean(x), mean = mean(x),
median = median(x), median = median(x),
user = dupfun(x)) user = dupfun(x))
} z <- unlist(lapply(split(z,i), centre))
if(duplicate!="strip"){ } else {
z <- unlist(lapply(split(z,i), centre)) z <- z[ord]
ord <- !duplicated(xy)
x <- x[ord]
y <- y[ord]
n <- length(x)
}
else{
ord <- (hist(i,plot=FALSE,freq=TRUE,breaks=seq(0.5,max(i)+0.5,1))$counts==1)
x <- x[ord]
y <- y[ord]
z <- z[ord]
n <- length(x)
}
} }
else x <- x[ord]
if(any(duplicated(xy))) y <- y[ord]
stop("duplicate data points") n <- length(x)
}
zo <- matrix(0, nx, ny) zo <- matrix(0, nx, ny)
storage.mode(zo) <- "double" storage.mode(zo) <- "double"
miss <- !extrap #if not extrapolating use missing values miss <- !extrap #if not extrapolating use missing values
...@@ -70,8 +69,7 @@ ...@@ -70,8 +69,7 @@
integer((31 + ncp) * n + nx * ny), integer((31 + ncp) * n + nx * ny),
double(5 * n), double(5 * n),
misso = as.logical(misso), misso = as.logical(misso),
PACKAGE = "akima") PACKAGE = "akima")[c("x", "y", "z", "misso")]
temp <- ans[c("x", "y", "z", "misso")] ans$z[ans$misso] <- NA
temp$z[temp$misso]<-NA ans[c("x", "y", "z")]
temp[c("x", "y", "z")]
} }
\name{interp} \name{interp}
\title{ \title{Gridded Bivariate Interpolation for Irregular Data}
Gridded Bivariate Interpolation for Irregular Data
}
\alias{interp} \alias{interp}
\alias{interp.new} \alias{interp.new}
\alias{interp.old} \alias{interp.old}
\description{
These functions implement bivariate interpolation onto a grid
for irregularly spaced input data. Bilinear or bicubic spline
interpolation is applied using different versions of algorithms from
Akima.
}
\usage{ \usage{
interp(x, y, z, xo=seq(min(x), max(x), length = 40), yo=seq(min(y), max(y), length = 40), ncp=0, extrap=FALSE, duplicate = "error", dupfun = NULL) interp(x, y, z, xo=seq(min(x), max(x), length = 40),
interp.old(x, y, z, xo= seq(min(x), max(x), length = 40), yo=seq(min(y), max(y), length = 40), ncp=0, extrap=FALSE, duplicate = "error", dupfun = NULL) yo=seq(min(y), max(y), length = 40),
interp.new(x, y, z, xo= seq(min(x), max(x), length = 40), yo=seq(min(y), max(y), length = 40), linear=FALSE, ncp=NULL, extrap=FALSE, duplicate = "error", dupfun = NULL) ncp = 0, extrap=FALSE, duplicate = "error", dupfun = NULL)
interp.old(x, y, z, xo= seq(min(x), max(x), length = 40),
yo=seq(min(y), max(y), length = 40), ncp = 0,
extrap=FALSE, duplicate = "error", dupfun = NULL)
interp.new(x, y, z, xo = seq(min(x), max(x), length = 40),
yo = seq(min(y), max(y), length = 40), linear = FALSE,
ncp = NULL, extrap=FALSE, duplicate = "error", dupfun = NULL)
} }
\arguments{ \arguments{
\item{x}{ \item{x}{
...@@ -22,72 +32,62 @@ interp.new(x, y, z, xo= seq(min(x), max(x), length = 40), yo=seq(min(y), max(y), ...@@ -22,72 +32,62 @@ interp.new(x, y, z, xo= seq(min(x), max(x), length = 40), yo=seq(min(y), max(y),
\item{z}{ \item{z}{
vector of z-coordinates of data points. vector of z-coordinates of data points.
Missing values are not accepted. Missing values are not accepted.
\code{x}, \code{y}, and \code{z} must be the same length and may
\code{x}, \code{y}, and \code{z} must be the same length and may contain no fewer contain no fewer than four points. The points of \code{x} and
than four points. The points of \code{x} and \code{y} \code{y} cannot be collinear, i.e, they cannot fall on the same line
cannot be collinear, i.e, they cannot fall on the same line (two vectors (two vectors \code{x} and \code{y} such that \code{y = ax + b} for
\code{x} and \code{y} such that \code{y = ax + b} for some \code{a}, \code{b} will not be some \code{a}, \code{b} will not be accepted). \code{interp} is
accepted). \code{interp} is meant for cases in which you have \code{x}, \code{y} meant for cases in which you have \code{x}, \code{y} values
values scattered over a plane and a \code{z} value for each. If, instead, scattered over a plane and a \code{z} value for each. If, instead,
you are trying to evaluate a mathematical function, or get a graphical you are trying to evaluate a mathematical function, or get a
interpretation of relationships that can be described by a polynomial, graphical interpretation of relationships that can be described by a
try \code{outer()}. polynomial, try \code{outer()}.
} }
\item{xo}{ \item{xo}{
vector of x-coordinates of output grid. The default is 40 points vector of x-coordinates of output grid. The default is 40 points
evenly spaced over the range of \code{x}. If extrapolation is not being evenly spaced over the range of \code{x}. If extrapolation is not being
used (\code{extrap=FALSE}, the default), \code{xo} should have a range that is used (\code{extrap=FALSE}, the default), \code{xo} should have a
close to or inside of the range of \code{x} for the results to be meaningful. range that is close to or inside of the range of \code{x} for the
} results to be meaningful.
\item{yo}{
vector of y-coordinates of output grid. The default is 40 points
evenly spaced over the range of \code{y}. If extrapolation is not being
used (\code{extrap=FALSE}, the default), \code{yo} should have a range that is
close to or inside of the range of \code{y} for the results to be meaningful.
} }
\item{linear}{logical, switch to linear interpolation in \code{interp.new}} \item{yo}{vector of y-coordinates of output grid; analogous to
\code{xo}, see above.}
\item{linear}{logical, switch to linear interpolation in \code{interp.new}.}
\item{ncp}{ \item{ncp}{
number of additional points to be used in computing partial number of additional points to be used in computing partial
derivatives at each data point. derivatives at each data point.
\code{ncp} must be either \code{0} (partial derivatives are not used), or at \code{ncp} must be either \code{0} (partial derivatives are not used), or at
least 2 but smaller than the number of data points (and smaller than least 2 but smaller than the number of data points (and smaller than
25). This option is only supported by \code{interp.old}. 25). This option is only supported by \code{interp.old}.
} }
\item{extrap}{ \item{extrap}{
logical flag: should extrapolation be used outside of the logical flag: should extrapolation be used outside of the
convex hull determined by the data points? convex hull determined by the data points?}
} \item{duplicate}{character string indicating how to handle duplicate
\item{duplicate}{ data points. Possible values are
indicates how to handle duplicate data points. Possible values are \describe{
\code{"error"} - produces an error message, \code{"strip"} - remove \item{\code{"error"}}{produces an error message,}
duplicate z values, \code{"mean"},\code{"median"},\code{"user"} - \item{\code{"strip"}}{remove duplicate z values,}
calculate mean , median or user defined function of duplicate z \item{ \code{"mean"},\code{"median"},\code{"user"}}{calculate
values.} mean , median or user defined function (\code{dupfun}) of duplicate
\item{dupfun}{this function is applied to duplicate points if \code{duplicate="user"} z values.}
} }}
\item{dupfun}{a function, applied to duplicate points if
\code{duplicate= "user"}.}
} }
\value{ \value{
list with 3 components: list with 3 components:
\item{x,y}{
\item{x}{ vectors of x- and y- coordinates of output grid, the same as the input
vector of x-coordinates of output grid, the same as the input argument \code{xo}, or \code{yo}, if present. Otherwise, their
argument \code{xo}, if present. Otherwise, a vector 40 points evenly spaced default, a vector 40 points evenly spaced over the range of the
over the range of the input \code{x}. input \code{x}.}
}
\item{y}{
vector of y-coordinates of output grid, the same as the input
argument \code{yo}, if present. Otherwise, a vector 40 points evenly spaced
over the range of the input \code{x}.
}
\item{z}{ \item{z}{
matrix of fitted z-values. The value \code{z[i,j]} is computed matrix of fitted z-values. The value \code{z[i,j]} is computed
at the x,y point \code{x[i], y[j]}. \code{z} has at the x,y point \code{xo[i], yo[j]}. \code{z} has
dimensions \code{length(x)} times \code{length(y)} (\code{length(xo)} times \code{length(yo)}). dimensions \code{length(xo)} times \code{length(yo)}.}
}
}}
\note{ \note{
\code{interp} is a wrapper for the two versions \code{interp.old} (it \code{interp} is a wrapper for the two versions \code{interp.old} (it
uses (almost) the same Fortran code from Akima 1978 as the S-Plus version) and uses (almost) the same Fortran code from Akima 1978 as the S-Plus version) and
...@@ -95,7 +95,7 @@ interp.new(x, y, z, xo= seq(min(x), max(x), length = 40), yo=seq(min(y), max(y), ...@@ -95,7 +95,7 @@ interp.new(x, y, z, xo= seq(min(x), max(x), length = 40), yo=seq(min(y), max(y),
(it is based on new Fortran code from Akima 1996). For linear (it is based on new Fortran code from Akima 1996). For linear
interpolation the old version is choosen, but spline interpolation is interpolation the old version is choosen, but spline interpolation is
done by the new version. done by the new version.
At the moment \code{interp.new} ignores \code{ncp} and does only At the moment \code{interp.new} ignores \code{ncp} and does only
bicubic spline interpolation. bicubic spline interpolation.
...@@ -103,18 +103,17 @@ interp.new(x, y, z, xo= seq(min(x), max(x), length = 40), yo=seq(min(y), max(y), ...@@ -103,18 +103,17 @@ interp.new(x, y, z, xo= seq(min(x), max(x), length = 40), yo=seq(min(y), max(y),
functions \code{contour} and \code{image}. Check the requirements of functions \code{contour} and \code{image}. Check the requirements of
these functions when choosing values for \code{xo} and \code{yo}. these functions when choosing values for \code{xo} and \code{yo}.
} }
\description{ \details{
If \code{ncp} is zero, linear If \code{ncp} is zero, linear
interpolation is used in the triangles bounded by data points. interpolation is used in the triangles bounded by data points.
Cubic interpolation is done if partial derivatives are used. Cubic interpolation is done if partial derivatives are used.
If \code{extrap} is \code{FALSE}, z-values for points outside the If \code{extrap} is \code{FALSE}, z-values for points outside the
convex hull are returned as \code{NA}. convex hull are returned as \code{NA}.
No extrapolation can be performed if \code{ncp} is zero. No extrapolation can be performed if \code{ncp} is zero.
The \code{interp} function handles duplicate \code{(x,y)} points
The \code{interp} function handles duplicate \code{(x,y)} points
in different ways. As default it will stop with an error message. But in different ways. As default it will stop with an error message. But
it can give duplicate points an unique \code{z} value according to the it can give duplicate points an unique \code{z} value according to the
parameter \code{duplicate} (\code{mean},\code{median} or any other parameter \code{duplicate} (\code{mean},\code{median} or any other
user defined function). user defined function).
...@@ -137,50 +136,75 @@ interp.new(x, y, z, xo= seq(min(x), max(x), length = 40), yo=seq(min(y), max(y), ...@@ -137,50 +136,75 @@ interp.new(x, y, z, xo= seq(min(x), max(x), length = 40), yo=seq(min(y), max(y),
} }
\seealso{ \seealso{
\code{\link[base]{contour}}, \code{\link[base]{image}}, \code{\link[base]{approx}}, \code{\link[base]{spline}}, \code{\link[base]{outer}}, \code{\link[base]{expand.grid}}. \code{\link{contour}}, \code{\link{image}},
\code{\link{approx}}, \code{\link{spline}},
\code{\link{outer}}, \code{\link{expand.grid}}.
} }
\examples{ \examples{
data(akima) data(akima)
# linear interpolation plot(y ~ x, data = akima, main = "akima example data")
with(akima, text(x, y, formatC(z,dig=2), adj = -0.1))
## linear interpolation
akima.li <- interp(akima$x, akima$y, akima$z) akima.li <- interp(akima$x, akima$y, akima$z)
image(akima.li$x,akima.li$y,akima.li$z) image (akima.li, add=TRUE)
contour(akima.li$x,akima.li$y,akima.li$z,add=TRUE) contour(akima.li, add=TRUE)
points(akima$x,akima$y) points (akima, pch = 3)
# increase smoothness ## increase smoothness (using finer grid):
akima.smooth <- interp(akima$x, akima$y, akima$z, akima.smooth <-
xo=seq(0,25, length=100), yo=seq(0,20, length=100)) with(akima, interp(x, y, z, xo=seq(0,25, length=100),
image(akima.smooth$x,akima.smooth$y,akima.smooth$z) yo=seq(0,20, length=100)))
contour(akima.smooth$x,akima.smooth$y,akima.smooth$z,add=TRUE) image (akima.smooth)
points(akima$x,akima$y) contour(akima.smooth, add=TRUE)
# use triangulation library to points(akima, pch = 3, cex = 2, col = "blue")
# show underlying triangulation: # use triangulation package to show underlying triangulation:
if(library(tripack, logical.return=TRUE)) if(library(tripack, logical.return=TRUE))
plot(tri.mesh(akima),add=TRUE,lty="dashed") plot(tri.mesh(akima), add=TRUE, lty="dashed")
# use only 15 points (interpolation only within convex hull!) # use only 15 points (interpolation only within convex hull!)
akima.part <- interp(akima$x[1:15],akima$y[1:15],akima$z[1:15]) akima.part <- with(akima, interp(x[1:15], y[1:15], z[1:15]))
image(akima.part$x,akima.part$y,akima.part$z) image (akima.part)
contour(akima.part$x,akima.part$y,akima.part$z,add=TRUE) contour(akima.part, add=TRUE)
points(akima$x[1:15],akima$y[1:15]) points(akima$x[1:15],akima$y[1:15])
# spline interpolation, use 5 points to calculate derivatives ## spline interpolation
# interp gives `linear interpolation not yet implemented with interp.new()' ## --------------------
akima.spl <- interp.old(akima$x, akima$y, akima$z, ## "Old": use 5 points to calculate derivatives -> many NAs
xo=seq(0,25, length=100), yo=seq(0,20, length=100),ncp=5) akima.sO <- interp.old(akima$x, akima$y, akima$z,
image(akima.spl$x,akima.spl$y,akima.spl$z) xo=seq(0,25, length=100), yo=seq(0,20, length=100), ncp=5)
contour(akima.spl$x,akima.spl$y,akima.spl$z,add=TRUE) table(is.na(akima.sO$z)) ## 3990 NA's; = 40 \%
points(akima$x,akima$y) akima.sO <- with(akima,
interp.old(x,y,z, xo=seq(0,25, length=100), yo=seq(0,20, len=100), ncp = 4))
sum(is.na(akima.sO$z)) ## still 3429
image (akima.sO) # almost useless
contour(akima.sO, add = TRUE)
## "New:"
akima.spl <- with(akima, interp.new(x,y,z, xo=seq(0,25, length=100),
yo=seq(0,20, length=100)))
contour(akima.spl) ; points(akima)
full.pal <- function(n) hcl(h = seq(340, 20, length = n))
cool.pal <- function(n) hcl(h = seq(120, 0, length = n) + 150)
warm.pal <- function(n) hcl(h = seq(120, 0, length = n) - 30)
filled.contour(akima.spl, color.palette = full.pal,
plot.axes = { axis(1); axis(2);
points(akima, pch = 3, col= hcl(c=100, l = 20))})
# no extrapolation!
## example with duplicate points :
# example with duplicate points
data(airquality) data(airquality)
air <- airquality[(!is.na(airquality$Temp) & air <- subset(airquality,
!is.na(airquality$Ozone) & !is.na(Temp) & !is.na(Ozone) & !is.na(Solar.R))
!is.na(airquality$Solar.R)),] # gives an error {duplicate ..}:
# gives an error: try( air.ip <- interp.new(air$Temp,air$Solar.R,air$Ozone) )