【问题标题】:Extract submatrix from matrix从矩阵中提取子矩阵
【发布时间】:2021-10-14 22:30:07
【问题描述】:

我在 R 中创建了一个 10x10(10 行和 10 列)的矩阵: matriz <- matrix(1:100, nrow = 10, ncol = 10, byrow=T) 我想从矩阵 (matriz) 中随机提取方形子矩阵 (3x3) 且不重叠。

我在 R 中看到一个名为“subset.matrix”的包,但我不能在随机矩阵中。

有什么建议吗?

【问题讨论】:

  • 随机不重叠是什么意思?您希望“提取”多少个子矩阵?如果它们不能重叠,那不是完全随机的吗?
  • 对不起!我的意思是,只要值不匹配,就可以从任何地方获取子矩阵

标签: r matrix submatrix


【解决方案1】:

我同意 user2974951 关于随机性的评论。但是,此代码块会按照您的要求执行。

matriz <- matrix(1:100, nrow = 10, ncol = 10, byrow=T)

attempts <- 50

# Initialize a list to hold the results
sub_mats <- vector(mode = "list", length = attempts)

# The top left corner of the matrix can't have an index > 8
rand_x <- sample(1:8, attempts, replace = T)
rand_y <- sample(1:8, attempts, replace = T)

for (i in 1:attempts) {
  # Get the three-length vectors
  x_range <- rand_x[i] : (rand_x[i] + 2)
  y_range <- rand_y[i] : (rand_y[i] + 2)
  # Subset the matrix
  sub_mat <- matriz[x_range, y_range]
  # We'll use NAs to mark submatrices from previous loops
  if (any(is.na(sub_mat))) next
  # If there's no overlap, add it to the list
  sub_mats[[i]] <- sub_mat
  # Set this submatrix as NAs
  matriz[x_range, y_range] <- rep(NA, 9)
}

# Remove failed attempts
sub_mats <- sub_mats[!sapply(sub_mats, is.null)]

您可以使用计数器来代替设定的循环尝试次数。通过 50 次尝试,我得到 4-6 个子矩阵。 1000 给出 6-8。

【讨论】:

    【解决方案2】:

    可以定义如下函数f

    f <- function(mat, submat.size = 3) {
      ridx <- Filter(function(x) length(x) == submat.size, split(sample(seq(nrow(mat))), ceiling(seq(nrow(mat)) / submat.size)))
      cidx <- Filter(function(x) length(x) == submat.size, split(sample(seq(ncol(mat))), ceiling(seq(ncol(mat)) / submat.size)))
      replicate(2, mat[ridx[[sample(length(ridx), 1)]], cidx[[sample(length(cidx), 1)]]], simplify = FALSE)
    }
    

    并且此函数使您能够生成一对随机不重叠的子矩阵>.

    示例结果

    > f(matriz)
    [[1]]
         [,1] [,2] [,3]
    [1,]   68   67   70
    [2,]   38   37   40
    [3,]   88   87   90
    
    [[2]]
         [,1] [,2] [,3]
    [1,]   63   62   69
    [2,]   33   32   39
    [3,]   83   82   89
    

    如果你每次都想要所有可能的独占随机子矩阵,你可以试试

    f2 <- function(mat, submat.size = 3) {
      ridx <- Filter(function(x) length(x) == submat.size, split(sample(seq(nrow(mat))), ceiling(seq(nrow(mat)) / submat.size)))
      cidx <- Filter(function(x) length(x) == submat.size, split(sample(seq(ncol(mat))), ceiling(seq(ncol(mat)) / submat.size)))
      r <- list()
      for (i in seq_along(ridx)) {
        for (j in seq_along(cidx)) {
          r[[length(r) + 1]] <- mat[ridx[[i]], cidx[[j]]]
        }
      }
      r
    }
    

    你会得到

    > f2(matriz)
    [[1]]
         [,1] [,2] [,3]
    [1,]    3    6    5
    [2,]   63   66   65
    [3,]   83   86   85
    
    [[2]]
         [,1] [,2] [,3]
    [1,]    2    8    4
    [2,]   62   68   64
    [3,]   82   88   84
    
    [[3]]
         [,1] [,2] [,3]
    [1,]    1   10    7
    [2,]   61   70   67
    [3,]   81   90   87
    
    [[4]]
         [,1] [,2] [,3]
    [1,]   13   16   15
    [2,]   33   36   35
    [3,]   23   26   25
    
    [[5]]
         [,1] [,2] [,3]
    [1,]   12   18   14
    [2,]   32   38   34
    [3,]   22   28   24
    
    [[6]]
         [,1] [,2] [,3]
    [1,]   11   20   17
    [2,]   31   40   37
    [3,]   21   30   27
    
    [[7]]
         [,1] [,2] [,3]
    [1,]   43   46   45
    [2,]   53   56   55
    [3,]   73   76   75
    
    [[8]]
         [,1] [,2] [,3]
    [1,]   42   48   44
    [2,]   52   58   54
    [3,]   72   78   74
    
    [[9]]
         [,1] [,2] [,3]
    [1,]   41   50   47
    [2,]   51   60   57
    [3,]   71   80   77
    

    【讨论】: