我目前正在大量使用density.ppp
函数,并使用我自己设计的不同内核函数来调用它。
对于我的项目,我还需要“重建”已经可用的内核功能,例如"gaussian"
和"quartic"
内核。
因此,我用density.ppp
调用了kernel = "gaussian"
并将其结果与使用自己的内核函数(生成高斯内核)调用density.ppp
的结果进行了比较。
我发现对于高斯内核,其行为与对其他内置内核的相同行为有很大不同。 kernel = "quartic"
。
我了解这是因为内核值是根据所使用的内核以不同方式计算的。对于除"gaussian"
-一个evaluate2Dkernel
以外的所有内核。另一方面,kernel = "gaussian"
的内核值计算被硬编码为densitypointsEngine
和second.moment.engine
。
我对此有两个主要问题:
如果使用at = "points"
和leaveoneout = FALSE
,
# ----- contribution from point itself ----------------
if(!leaveoneout) {
# add contribution from point itself
self <- const
if(!is.null(weights))
self <- self * weights
result <- result + self
}
被执行。
在此之前,已设置const
。对于除
"gaussian"
-一个,我们有const <- 1/sigma^2
。对于kernel = "gaussian"
,const
是
然后将其设置为const <- const/(2*pi)
以便将其用作
硬编码内核中指数函数之前的常量
值计算:
# constant factor in density computations
if(is.null(varcov)) {
const <- 1/sigma^2
} else {
detSigma <- det(varcov)
Sinv <- solve(varcov)
const <- 1/sqrt(detSigma)
}
if(isgauss) {
# absorb leading constant in Gaussian density
const <- const/(2 * pi)
}
我认为这是不正确的,因为它应始终为未排除的点添加1/sigma^2
,但如果kernel = "gaussian"
则应添加1/2*pi*(sigma^2)
。我对吗?
不知何故,我暂时确信,kernel = "gaussian"
与高斯核重建的结果也有所不同,因为在second.moment.engine
中发现了
# set up kernel
xcol.ker <- xstep * c(0:(nc-1),-(nc:1))
yrow.ker <- ystep * c(0:(nr-1),-(nr:1))
kerpixarea <- xstep * ystep
if(identical(kernel, "gaussian")) {
if(!is.null(sigma)) {
densX.ker <- dnorm(xcol.ker, sd=sigma)
densY.ker <- dnorm(yrow.ker, sd=sigma)
#' WAS: Kern <- outer(densY.ker, densX.ker, "*") * kerpixarea
Kern <- outer(densY.ker, densX.ker, "*")
Kern <- Kern/sum(Kern)
} else if(!is.null(varcov)) {
## anisotropic kernel
detSigma <- det(varcov)
Sinv <- solve(varcov)
halfSinv <- Sinv/2
constker <- kerpixarea/(2 * pi * sqrt(detSigma))
xsq <- matrix((xcol.ker^2)[col(Ypad)], ncol=2*nc, nrow=2*nr)
ysq <- matrix((yrow.ker^2)[row(Ypad)], ncol=2*nc, nrow=2*nr)
xy <- outer(yrow.ker, xcol.ker, "*")
Kern <- constker * exp(-(xsq * halfSinv[1,1]
+ xy * (halfSinv[1,2]+halfSinv[2,1])
+ ysq * halfSinv[2,2]))
Kern <- Kern/sum(Kern)
} else
stop("Must specify either sigma or varcov")
} else {
## non-Gaussian kernel
## evaluate kernel at array of points
xker <- as.vector(xcol.ker[col(Ypad)])
yker <- as.vector(yrow.ker[row(Ypad)])
Kern <- evaluate2Dkernel(kernel, xker, yker,
sigma=sigma, varcov=varcov, ...) * kerpixarea
Kern <- matrix(Kern, ncol=2*nc, nrow=2*nr)
Kern <- Kern/sum(Kern)
}
仅当内核不是kerpixarea
时,才与"gaussian"
进行乘法。但是经过一番测试,我发现由于Kern <- Kern / sum(Kern)
行,乘法是否完成并不重要。
但是我不知道为什么它仍然存在?
#' WAS: Kern <- outer(densY.ker, densX.ker, "*") * kerpixarea
注释意味着对kernel = "gaussian"
进行了更改以避免这种不必要的计算,对吗?那么为什么其他内核仍然存在呢?
答案 0 :(得分:0)
在density.ppp
,at="points"
和leaveoneout=FALSE
不是默认值的情况下,您在kernel
的代码中发现了一个错误。在这种情况下,距离零处的内核值无法正确评估。
该错误将很快在spatstat
的开发版本中修复。
关于您的其他问题,恐怕我没有时间解释我们对这段代码的处理方式。它仍在开发中(如注释"Experimental code"
所示),以使其运行更快。已有旧代码,因此我们可以检查它是否仍然有效。