问题
I am trying to find a function in R which smooths a 2D matrix which is already padded by zero around the matrix depending on the length of the window. If the window size is 3 then we pas 3 zeros from the top, bottom, right and left and then we do the averaging to smooth it. I found rollmean in SO and other tutorials but it doesn't exactly do what I want. I need (say if the window size is 3) we consider a window of 3*3 and take the average and replace it by the current elements of the current window and then move the window to the right by one unit (pixel). And for example when we reach the rightmost end, we start windowing by coming one unit down from the leftmost corner. This is what rollmean do which I don't want. I want all my 9 elements to be preserved.
> xm<-matrix(c(1,2,3,4,5,6,7,8,9),ncol=3)
> xm
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
> rollmean(xm,3)
[,1] [,2] [,3]
[1,] 2 5 8
So here's the padding function as described above:
mat.pad<-function(X,k){
dims<-dim(X)
n<-dims[1]
m<-dims[2]
pad.X <- matrix(0, n + 2 * k, m + 2 * k)
pad.X[(k + 1):(n + k), (k + 1):(m + k)] <- X
return(pad.X)
}
So imagine that this is my X:
> X
[,1] [,2] [,3]
[1,] 0.5 0.3 0.2
[2,] 0.5 0.4 0.1
[3,] 0.4 0.4 0.3
[4,] 0.4 0.3 0.3
[5,] 0.3 0.2 0.2
[6,] 0.5 0.2 0.2
[7,] 0.5 0.4 0.1
[8,] 0.4 0.4 0.5
[9,] 0.3 0.3 0.5
and here's the padded version with k=3 (window =3*3)
> mat.pad(X,3)
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
[1,] 0 0 0 0.0 0.0 0.0 0 0 0
[2,] 0 0 0 0.0 0.0 0.0 0 0 0
[3,] 0 0 0 0.0 0.0 0.0 0 0 0
[4,] 0 0 0 0.5 0.3 0.2 0 0 0
[5,] 0 0 0 0.5 0.4 0.1 0 0 0
[6,] 0 0 0 0.4 0.4 0.3 0 0 0
[7,] 0 0 0 0.4 0.3 0.3 0 0 0
[8,] 0 0 0 0.3 0.2 0.2 0 0 0
[9,] 0 0 0 0.5 0.2 0.2 0 0 0
[10,] 0 0 0 0.5 0.4 0.1 0 0 0
[11,] 0 0 0 0.4 0.4 0.5 0 0 0
[12,] 0 0 0 0.3 0.3 0.5 0 0 0
[13,] 0 0 0 0.0 0.0 0.0 0 0 0
[14,] 0 0 0 0.0 0.0 0.0 0 0 0
[15,] 0 0 0 0.0 0.0 0.0 0 0 0
How can I slide the window of averaging also?
回答1:
I'm not sure I got the idea but I think it could be approached with raster::focal?
.
See this post
library(raster)
x <- matrix(c(1,2,3,4,5,6,7,8,9),ncol=3)
x
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
r <- raster(x) # convert to rasterLayer
## sliding a 3x3 window
agg <- as.matrix(focal(r, matrix(1, 3, 3), mean, pad = T, padValue = 0))
agg
[,1] [,2] [,3]
[1,] 1.333333 3.000000 2.666667
[2,] 2.333333 5.000000 4.333333
[3,] 1.777778 3.666667 3.111111
Running on your example
x2 <- mat.pad(X=x, 3)
r2 <- raster(x2)
as.matrix(focal(r2, matrix(1, 3, 3), mean, pad = T, padValue = 0))
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
[1,] 0 0 0.0000000 0.0000000 0.000000 0.000000 0.0000000 0 0
[2,] 0 0 0.0000000 0.0000000 0.000000 0.000000 0.0000000 0 0
[3,] 0 0 0.1111111 0.5555556 1.333333 1.222222 0.7777778 0 0
[4,] 0 0 0.3333333 1.3333333 3.000000 2.666667 1.6666667 0 0
[5,] 0 0 0.6666667 2.3333333 5.000000 4.333333 2.6666667 0 0
[6,] 0 0 0.5555556 1.7777778 3.666667 3.111111 1.8888889 0 0
[7,] 0 0 0.3333333 1.0000000 2.000000 1.666667 1.0000000 0 0
[8,] 0 0 0.0000000 0.0000000 0.000000 0.000000 0.0000000 0 0
[9,] 0 0 0.0000000 0.0000000 0.000000 0.000000 0.0000000 0 0
来源:https://stackoverflow.com/questions/23622379/smoothing-a-2d-matrix-with-rollmean-filter-rollapply-or-other-r-facilities-by