# How to replace a spot of cells by surrounding cells value in a matrix (R)

Solution for How to replace a spot of cells by surrounding cells value in a matrix (R)
is Given Below:

I obtain a matrix from a calculation. This matrix can have spots of 1 while the rest of the matrix presents values of 0, 2 and 3.

``````> ##Working folder
> setwd("C:/Users/laure/Desktop/Code")
> mat <- as.matrix(mat)
> mat
X1 X1.1 X0 X0.1 X0.2 X0.3 X1.2 X1.3
[1,]  1    0  0    0    3    0    0    2
[2,]  1    2  0    3    1    1    0    0
[3,]  0    0  0    0    3    1    0    0
[4,]  2    0  0    0    0    0    0    0
[5,]  0    0  0    0    0    0    2    2
[6,]  0    0  1    0    0    0    2    2
[7,]  0    1  1    1    0    0    2    2
[8,]  0    0  1    1    0    0    2    2
[9,]  0    0  1    0    0    0    0    0
[10,]  0    0  0    0    0    0    0    0
[11,]  0    0  0    0    2    0    0    1
[12,]  0    0  0    0    2    2    1    1
[13,]  1    1  0    0    0    0    1    1
[14,]  1    1  0    0    0    1    1    1
[15,]  1    1  1    0    0    1    1    1
``````

I would like to replace all the spots of 1 that are completely surrounded by cell values of 0 (in this example have only 1 spot completely surrounded by 0). I do not want to include the spot of 1 on the borders as there are not completely surrounded. I do not know the location and the number of the spots as it depends of the calculation performed before.

I can find the all spots having value of 1 using `clump` function but how to find the surrounding cells value and replace the spot cells.

``````####convert matrix into raster
r <-raster(mat)

####select cells with criteria based on cell value
rx <- r == 1

###extract IDs of clumps according the criteria
rc <- clump(rx)
f <- freq(rc, useNA="no")
> f
value count
[1,]     1     2
[2,]     2     3
[3,]     3     7
[4,]     4    11
[5,]     5     7
``````

Adopting the approach from `compute_neighb_sum` you can use the following code:

``````embed_matrix <- function(mx) {
cbind(Inf, rbind(Inf, mx, Inf), Inf)
}

disembed_matrix <- function(mx) {
mx[-c(1, nrow(mx)), -c(1, ncol(mx)), drop = FALSE]
}

is_valid_idx <- function(idx, dim) {
rowSums(t(t(idx) > dim | t(idx) < 0)) == 0
}

sum_neighbor_cells <- function(m, include_corner = TRUE, include_element = FALSE) {
em <- embed_matrix(m)
dims <- dim(em)
offsets <- as.matrix(expand.grid(r = -1:1, c = -1:1))
exclude_offsets <- matrix(integer(0), ncol = 2)
if (!include_element) {
exclude_offsets <- rbind(exclude_offsets, c(0, 0))
}
if (!include_corner) {
exclude_offsets <- rbind(exclude_offsets,
matrix(c(-1, -1, 1, 1, -1, 1, -1, 1), ncol = 2))
}
dupes <- duplicated(rbind(offsets, exclude_offsets), fromLast = TRUE)
offsets <- offsets[!dupes[seq_len(nrow(offsets))], , drop = FALSE]
idx <- cbind(c(row(em)), c(col(em)))
res <- apply(offsets, 1, function(row) {
t(t(idx) + row)
})
dim(res) <- c(dim(idx), nrow(offsets))
idx <- aperm(res, 3:1)
res <- apply(idx, 3, function(i) {
valid_idx <- i[is_valid_idx(i, dims), ,
drop = FALSE]
sum(em[valid_idx])
})
dim(res) <- dims
res <- disembed_matrix(res)
res
}
``````

Then you can use `sum_neighbor_cells` to get the sum of all neighboring cells (with ot without the corner cells):

``````set.seed(123)
(m <- matrix(sample(0:1, 25, TRUE), 5))
#      [,1] [,2] [,3] [,4] [,5]
# [1,]    0    1    1    0    0
# [2,]    0    1    1    1    1
# [3,]    0    1    1    0    0
# [4,]    1    0    0    0    0
# [5,]    0    0    1    0    0

sum_neighbor_cells(m, include_corner = FALSE)
#      [,1] [,2] [,3] [,4] [,5]
# [1,]  Inf  Inf  Inf  Inf  Inf
# [2,]  Inf    3    4    2  Inf
# [3,]  Inf    2    2    2  Inf
# [4,]  Inf    2    2    0  Inf
# [5,]  Inf  Inf  Inf  Inf  Inf
sum_neighbor_cells(m, include_corner = TRUE)
#      [,1] [,2] [,3] [,4] [,5]
# [1,]  Inf  Inf  Inf  Inf  Inf
# [2,]  Inf    5    6    4  Inf
# [3,]  Inf    4    4    4  Inf
# [4,]  Inf    4    3    2  Inf
# [5,]  Inf  Inf  Inf  Inf  Inf
``````

With this function you can get the indices of cells with have only `0's` as neighboring cells easily via:

``````(idx <- which(sum_neighbor_cells(m, include_corner = FALSE) == 0, arr.ind = TRUE))
#      row col
# [1,]   4   4
m[idx] <- NA
m
#      [,1] [,2] [,3] [,4] [,5]
# [1,]    0    1    1    0    0
# [2,]    0    1    1    1    1
# [3,]    0    1    1    0    0
# [4,]    1    0    0   NA    0
# [5,]    0    0    1    0    0
``````