Consider my 20x20 matrix:
M1 <- matrix(rnorm(400), nrow=20, ncol=20)
What I am trying to do is:
So far I have managed to do this for all the columns with a fixed block of rows:
x <- 0:20
for (i in seq_along(x)) {
matrixtest[i] <- median(as.matrix(M1[1:5, (1 + i):(5 + i)]))
M1[3, 3 + seq_along(x)] <- matrixtest[seq_along(x)]
}
However, the problem is I want to also do this going down each row, and I can't figure out a way to do it without manually specifying the rows as I have done below.
matrixtest2[i] <- median(as.matrix(M1[2:6, (1 + i):(5 + i)]))
matrixtest3[i] <- median(as.matrix(M1[3:7, (1 + i):(5 + i)]))
matrixtest4[i] <- median(as.matrix(I[4:8, (1 + i):(5 + i)]))
M1[4, 4 + seq_along(x)] <- matrixtest2[seq_along(x)]
M1[5, 5 + seq_along(x)] <- matrixtest3[seq_along(x)]
M1[6, 6 + seq_along(x)] <- matrixtest4[seq_along(x)]
This approach is obviously undesirable - any insights on how to do this, either with a for
loop or apply
statement would be most appreciated, thanks.
Using a double for
loop.
> n <- 5L ## define block length
> res <- vector('list', (n - 1L)^2) ## initialize result vector
> for (i in seq_len(nrow(M1) - n + 1) - 1L) {
+ for (j in seq_len(nrow(M1) - n + 1) - 1L) {
+ tmp <- M1[1:n + i, 1:n + j]
+ res[[i + 1L]][[j + 1L]] <- replace(tmp, ceiling(length(tmp)/2), median(tmp))
+ }
+ }
>
> res[[1]][[1]]
[,1] [,2] [,3] [,4] [,5]
[1,] 1 4 1 4 7
[2,] 5 2 5 9 2
[3,] 1 8 4 3 5
[4,] 9 3 6 5 6
[5,] 4 1 6 8 3
>
> identical(res[[1]][[1]], replace(M1[1:5, 1:5], 13, median(M1[1:5, 1:5])))
[1] TRUE
Data:
set.seed(42)
M1 <- matrix(sample(1:9, 400, replace=TRUE), nrow=20, ncol=20)