1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
|
#
# nncorr.R
#
# $Revision: 1.12 $ $Date: 2019/01/22 03:08:57 $
#
nnmean <- function(X, k=1, na.action="warn") {
stopifnot(is.ppp(X))
if(!is.marked(X, na.action=na.action))
stop("X must be a marked point pattern", call.=FALSE)
if(k %% 1 != 0 || length(k) != 1 || k <= 0)
stop("k should be a single integer greater than 0", call.=FALSE)
m <- numeric.columns(marks(X), logical=TRUE, others="na")
## default result
nana <- rep(NA_real_, ncol(m))
ans <- rbind(unnormalised=nana,
normalised=nana)
##
if(all(is.na(m))) {
warning("non-numeric marks; results are NA", call.=FALSE)
} else if(k >= npoints(X)) {
warning(paste("Not enough points to compute k-th nearest neighbours",
paste0(paren(paste0("n = ", npoints(X), ", k = ", k)), ";"),
"results are NA"),
call.=FALSE)
} else {
nnid <- nnwhich(X, k=k)
ok <- (nndist(X, k=k) <= bdist.points(X))
if(!any(ok, na.rm=TRUE)) {
warning("insufficient data remaining after border correction; results are NA")
} else {
numer <- sapply(as.data.frame(m[nnid[ok], ]), mean, na.rm=TRUE)
denom <- sapply(as.data.frame(m), mean, na.rm=TRUE)
ans <- rbind(unnormalised=numer,
normalised =numer/denom)
}
}
if(ncol(ans) == 1) ans <- ans[,1,drop=TRUE]
return(ans)
}
nnvario <- local({
nnvario <- function(X, k=1, na.action="warn") {
stopifnot(is.ppp(X))
if(!is.marked(X, na.action=na.action))
stop("X must be a marked point pattern", call.=FALSE)
m <- numeric.columns(marks(X), logical=TRUE, others="na")
if(all(is.na(m))) warning("non-numeric marks; results are NA", call.=FALSE)
ans <- nncorr(X %mark% m, sqdif, k=k, denominator=diag(var(m)),
na.action="ignore")
return(ans)
}
sqdif <- function(m1,m2) { ((m1-m2)^2)/2 }
nnvario
})
nncorr <- function(X, f = function(m1,m2) { m1 * m2},
k=1,
...,
use = "all.obs",
method = c("pearson", "kendall", "spearman"),
denominator=NULL,
na.action="warn") {
stopifnot(is.ppp(X))
if(!is.marked(X, na.action=na.action))
stop("X must be a marked point pattern", call.=FALSE)
if(k %% 1 != 0 || length(k) != 1 || k <= 0)
stop("k should be a single integer greater than 0", call.=FALSE)
if(k >= npoints(X))
stop("Not enough points to compute k-th nearest neighbours")
m <- as.data.frame(marks(X))
nv <- ncol(m)
if(nv == 1) colnames(m) <- ""
#
if(missing(method) || is.null(method))
method <- "pearson"
#
if(missing(f)) f <- NULL
if(!is.null(f) && !is.function(f)) {
if(nv == 1) stop("f should be a function")
# could be a list of functions
if(!(is.list(f) && all(unlist(lapply(f, is.function)))))
stop("f should be a function or a list of functions")
if(length(f) != nv)
stop("Length of list f does not match number of mark variables")
}
# optional denominator(s)
if(!is.null(denominator) && !(length(denominator) %in% c(1, nv)))
stop("Denominator has incorrect length")
# multi-dimensional case
if(nv > 1) {
# replicate things
if(is.function(f)) f <- rep.int(list(f), nv)
if(length(denominator) <= 1) denominator <- rep.int(list(denominator), nv)
#
result <- matrix(NA, nrow=3, ncol=nv)
outnames <- c("unnormalised", "normalised", "correlation")
dimnames(result) <- list(outnames, colnames(m))
for(j in 1:nv) {
mj <- m[,j, drop=FALSE]
denj <- denominator[[j]]
nncj <- nncorr(X %mark% mj, f=f[[j]], k=k, use=use, method=method,
denominator=denj)
kj <- length(nncj)
result[1:kj,j] <- nncj
}
if(all(is.na(result[3, ]))) result <- result[1:2, ]
return(result)
}
# one-dimensional
m <- m[,1,drop=TRUE]
# select 'f' appropriately for X
chk <- check.testfun(f, X=X)
f <- chk$f
ftype <- chk$ftype
# denominator
Efmm <-
if(!is.null(denominator)) denominator else
switch(ftype,
mul={
mean(m)^2
},
equ={
sum(table(m)^2)/length(m)^2
},
general={
mean(outer(m, m, f, ...))
})
# border method
nn <- nnwhich(X, k=k)
ok <- (nndist(X, k=k) <= bdist.points(X))
if(!any(ok))
stop("Insufficient data")
mY <- m[nn[ok]]
mX <- m[ok]
Efmk <- switch(ftype,
mul = {
mean(mX * mY, ...)
},
equ = {
mean(mX == mY, ...)
},
general = {
mean(f(mX, mY, ...))
})
#
answer <- c(unnormalised=Efmk,
normalised=Efmk/Efmm)
if(ftype == "mul") {
classic <- cor(mX, mY, use=use, method=method)
answer <- c(answer, correlation=classic)
}
return(answer)
}
|