【问题标题】:How to replace a spot of cells by surrounding cells value in a matrix (R)如何通过矩阵中的周围单元格值替换一个单元格(R)
【发布时间】:2021-08-03 00:25:43
【问题描述】:

我从计算中得到一个矩阵。这个矩阵的点可以是 1,而矩阵的其余部分的值是 0、2 和 3。

> ##Working folder
> setwd("C:/Users/laure/Desktop/Code")
> ##Load matrix from excel
> mat <- read.csv("test.csv",  header = TRUE)
> 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

我想替换所有被 0 单元格值完全包围的 1 点(在此示例中,只有 1 个点完全被 0 包围)。我不想在边界上包括 1 的位置,因为没有完全包围。我不知道点的位置和数量,因为这取决于之前执行的计算。

我可以使用 clump 函数找到所有值为 1 的点,但是如何找到周围的单元格值并替换点单元格。

####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

【问题讨论】:

  • 这是一种卷积类型的程序。您可以使用 for 循环来完成此操作
  • 您可以使用 stackoverflow.com/questions/25596807/… 中的 compute_neighb_sum 函数来计算相邻单元格的总和。当结果为 0 时,您可以替换该值。
  • 您的示例中会出现哪个1?我看不出来...

标签: r matrix raster


【解决方案1】:

采用compute_neighb_sum的方法可以使用如下代码:

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
}

然后您可以使用sum_neighbor_cells 来获取所有相邻单元格的总和(有 ot 没有角单元格):

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

使用此函数,您可以通过以下方式轻松获取只有0's 作为相邻单元格的单元格的索引:

(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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-21
    • 2019-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多