我写了一个函数来解决我的问题。这是我称为kernelsmooth 的函数。它需要三个参数,一个要平滑的数据矩阵、一个内核和一个布尔标志 norm,如果为真,则通过其值的平均值对内核进行归一化(防止矩阵数据膨胀)。
kernelsmooth <- function(x, kern, norm=TRUE) {
# how many rows/cols of zeroes are used to pad.
width <- dim(kern)[1]
pad <- floor(width / 2)
# record the width and height the input data matrix
x_w <- ncol(x)
x_h <- nrow(x)
# Are we normalizing the kernel?
if (norm == TRUE) {
k <- kern / sum(abs(kern))
} else {
k <- kern
}
# pad all around the matrix an equal width of zeros
x_pad <- t(padzeros(data=x, nzeros=pad, side="both"))
x_pad <- t(padzeros(data=x_pad, nzeros=pad, side="both"))
# Pre-allocate the final (smoothed) data matrix
s <- matrix(0, nrow = x_h, ncol = x_w)
# Pre-allocate a temporary matrix for the iterative calculations
temp <- matrix(0, width, width)
# Loop through the data to apply the kernel.
for (col in 1:x_w ) {
for (row in 1:x_h ) {
temp <- x_pad[row:(row + width - 1), col:(col + width - 1)]
s[row,col] <- sum(k * temp)
}
}
# return the smoothed data
return(s)
}
一些例子:
-
不要平滑矩阵(应用类似于单位矩阵的单位核)。
kernelsmooth(x = matrix(2,5,5), kern = matrix(c(0,0,0, 0,1,0, 0,0,0) , 3, 3))
输出:
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 2 2 2 2 2 2
[2,] 2 2 2 2 2 2
[3,] 2 2 2 2 2 2
[4,] 2 2 2 2 2 2
[5,] 2 2 2 2 2 2
[6,] 2 2 2 2 2 2
-
平均平滑(每个元素通过其自身及其相邻元素的平均值进行平滑):
kernelsmooth(x = matrix(4,5,5), kern = matrix(1,3,3))
输出:
[,1] [,2] [,3] [,4] [,5]
[1,] 1.777778 2.666667 2.666667 2.666667 1.777778
[2,] 2.666667 4.000000 4.000000 4.000000 2.666667
[3,] 2.666667 4.000000 4.000000 4.000000 2.666667
[4,] 2.666667 4.000000 4.000000 4.000000 2.666667
[5,] 1.777778 2.666667 2.666667 2.666667 1.777778
-
高斯平滑(各向同性平滑):
高斯
输出:
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,] 2.491349 3.321799 3.529412 3.529412 3.529412 3.529412 3.321799 2.491349
[2,] 3.321799 4.429066 4.705882 4.705882 4.705882 4.705882 4.429066 3.321799
[3,] 3.529412 4.705882 5.000000 5.000000 5.000000 5.000000 4.705882 3.529412
[4,] 3.529412 4.705882 5.000000 5.000000 5.000000 5.000000 4.705882 3.529412
[5,] 3.529412 4.705882 5.000000 5.000000 5.000000 5.000000 4.705882 3.529412
[6,] 3.529412 4.705882 5.000000 5.000000 5.000000 5.000000 4.705882 3.529412
[7,] 3.321799 4.429066 4.705882 4.705882 4.705882 4.705882 4.429066 3.321799
[8,] 2.491349 3.321799 3.529412 3.529412 3.529412 3.529412 3.321799 2.491349