How to combine data from different columns, e.g. mean of surrounding columns for a given column

StackOverflow https://stackoverflow.com/questions/23337406

  •  10-07-2023
  •  | 
  •  

Question

I am trying to smooth a matrix by attributing the mean value of a window covering n columns around a given column. I've managed to do it but I'd like to see how would be 'the R way' of doing it as I am making use of for loops. Is there a way to get this using apply or some function of the same family?

Example:

# create a toy matrix
mat <- matrix(ncol=200);
for(i in 1:100){ mat <- rbind(mat,sample(1:200, 200) )}
# quick visualization
image(t(mat))

enter image description here

This is the matrix before smoothing:

I wrote the function smooth_mat that takes a matrix and the length of the smoothing kernel:

smooth_row_mat <- function(k, k.d=5){
    k.range <- (k.d + 2):(ncol(k) - k.d - 1)
    k.smooth <- matrix(nrow=nrow(k))
    for( i in k.range){
            if (i  %% 10 == 0)      cat('\r',round(i/length(k.range), 2))
            k.smooth <- cbind( k.smooth, rowMeans(k[,c(  (i-1-k.d):(i-1) ,i, (i+1):(i + 1 - k.d) )]) )
    }
    return(k.smooth)

}

Now we use smooth_row_mat() with mat

mat.smooth <- smooth_mat(mat)

And we have successfully smoothed, on a row basis, the content of the matrix.

This is the matrix after: enter image description here

This method is good for such a small matrix although my real matrices are around 40,000 x 400, still works but I'd like to improve my R skills.

Thanks!

Was it helpful?

Solution

You can apply a filter (running mean) across each row of your matrix as follows:

apply(k, 1, filter, rep(1/k.d, k.d))

OTHER TIPS

Here's how I'd do it, with the raster package.

First, create a matrix filled with random data and coerce it to a raster object.

library(raster)
r <- raster(matrix(sample(200, 200*200, replace=TRUE), nc=200))
plot(r)

enter image description here

Then use the focal function to calculate a neighbourhood mean for a neighbourhood of n cells either side of the focal cell. The values in the matrix of weights you provide to the focal function determine how much the value of each cell contributes to the focal summary. For a mean, we say we want each cell to contribute 1/n, so we fill a matrix of n columns, with values 1/n. Note that n must be an odd number, and the cell in the centre of the matrix is considered the focal cell.

n <- 3
smooth_r <- focal(r, matrix(1/n, nc=n))
plot(smooth_r)

enter image description here

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top