#
# derivfv.R
#
# differentiation for fv objects
#
# $Revision: 1.7 $ $Date: 2018/09/28 05:12:08 $
#
deriv.fv <- local({
derivative <- function(y, r, ...) {
ss <- smooth.spline(r, y, ...)
predict(ss, r, deriv=1)$y
}
deriv.fv <- function(expr, which="*", ...,
method=c("spline", "numeric"),
kinks=NULL,
periodic=FALSE,
Dperiodic=periodic) {
f <- expr
method <- match.arg(method)
## select columns
## if(length(which) == 1L && which %in% .Spatstat.FvAbbrev) {
if(length(which) == 1L) {
if(which == ".x")
stop("Cannot smooth the function argument")
which <- fvnames(f, which)
}
if(any(nbg <- !(which %in% names(f))))
stop(paste("Unrecognised column",
ngettext(sum(nbg), "name", "names"),
commasep(sQuote(which[nbg])),
"in argument", sQuote("which")))
relevant <- names(f) %in% which
## get
rname <- fvnames(f, ".x")
df <- as.data.frame(f)
rpos <- which(colnames(df) == rname)
rvals <- df[,rpos]
yvals <- df[,relevant,drop=FALSE]
nr <- length(rvals)
##
if(Dperiodic) {
## Derivative should be periodic
## Recycle data to imitate periodicity
DR <- diff(range(rvals))
rvals <- c(rvals[-nr] - DR, rvals, rvals[-1L] + DR)
yleft <- yvals[-nr, , drop=FALSE]
yright <- yvals[-1L, , drop=FALSE]
if(!periodic) {
## original data are not periodic (e.g. cdf of angular variable)
## but derivative must be periodic
jump <- matrix(as.numeric(yvals[nr,] - yvals[1L, ]),
nr-1L, ncol(yvals), byrow=TRUE)
yleft <- yleft - jump
yright <- yright + jump
}
yvals <- rbind(yleft, yvals, yright)
actual <- nr:(2*nr - 1L)
NR <- length(rvals)
} else {
NR <- nr
actual <- 1:nr
}
## cut x axis into intervals?
if(is.null(kinks)) {
cutx <- factor(rep(1, NR))
} else {
rr <- range(rvals)
if(periodic)
kinks <- c(kinks-DR, kinks, kinks+DR)
breaks <- sortunique(kinks)
if(breaks[1L] > rr[1L]) breaks <- c(rr[1L], breaks)
if(max(breaks) < rr[2L]) breaks <- c(breaks, rr[2L])
cutx <- cut(rvals, breaks=breaks, include.lowest=TRUE)
}
## process
for(segment in levels(cutx)) {
ii <- (cutx == segment)
yy <- yvals[ii, , drop=FALSE]
switch(method,
numeric = {
dydx <- apply(yy, 2, diff)/diff(rvals[ii])
nd <- nrow(dydx)
dydx <- rbind(dydx, dydx[nd, ])
},
spline = {
dydx <- apply(yy, 2, derivative,
r=rvals[ii], ...)
})
df[ii[actual], relevant] <- dydx[ actual, ]
}
## pack up
result <- f
result[,] <- df
## tweak name of function
if(!is.null(yl <- attr(f, "ylab")))
attr(result, "ylab") <- substitute(bold(D)~Fx, list(Fx=yl))
if(!is.null(ye <- attr(f, "yexp")))
attr(result, "yexp") <- substitute(bold(D)~Fx, list(Fx=ye))
## tweak mathematical labels
attr(result, "labl")[relevant] <-
paste0("bold(D)~", attr(f, "labl")[relevant])
return(result)
}
deriv.fv
})
increment.fv <- function(f, delta) {
stopifnot(is.fv(f))
check.1.real(delta)
stopifnot(delta > 0)
half <- delta/2
xx <- with(f, .x)
ynames <- fvnames(f, ".")
yy <- as.data.frame(lapply(ynames,
function(a, xx, f, h) {
g <- as.function(f, value=a)
g(xx+h)-g(xx-h)
},
xx=xx, f=f, h=half))
Y <- f
Y[,ynames] <- yy
## tweak name of function
if(!is.null(yl <- attr(f, "ylab")))
attr(Y, "ylab") <- substitute(Delta~Fx, list(Fx=yl))
if(!is.null(ye <- attr(f, "yexp")))
attr(Y, "yexp") <- substitute(Delta~Fx, list(Fx=ye))
## tweak mathematical labels
relevant <- colnames(Y) %in% ynames
attr(Y, "labl")[relevant] <-
paste0("Delta~", attr(f, "labl")[relevant])
## tweak recommended range
attr(Y, "alim") <- intersect.ranges(attr(f, "alim"),
range(xx) + c(1,-1)*half)
return(Y)
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.