【问题标题】:Matrix calculations within an R functionR 函数中的矩阵计算
【发布时间】:2022-01-15 08:18:13
【问题描述】:

我正在尝试编写一个函数,该函数将识别 nxm 矩阵 M 的哪一行最接近长度为 m 的向量 y。

请问我在代码中做错了什么?我的目标是让函数产生一个长度为 n 的列向量,它给出矩阵的每一行坐标与向量 y 之间的距离。然后我想输出最接近向量点的矩阵的行号。

closest.point <- function(M, y) {
  p <- length(y)
  k <- nrow(M)
  T <- matrix(nrow=k)
  T <- for(i in 1:n) 
    for(j in 1:m) {
      (X[i,j] - x[j])^2 + (X[i,j] - x[j])^2
    }
  W <- rowSums(T)
  max(W)
  df[which.max(W),]
}

【问题讨论】:

    标签: r matrix


    【解决方案1】:

    即使已经有更好的方法(在处理矩阵时不使用 for 循环)来解决这个问题,我还是想用 for 循环为您的方法提供一个解决方案。

    您的函数中有一些错误。有一些未定义的变量,例如 n、m 或 X。

    同时尽量避免将变量命名为 T,因为 R 将 T 解释为 TRUE。它可以工作,但如果在以下代码行中使用 T 作为 TRUE,可能会导致一些错误。

    循环时,您需要为要更新的变量提供索引,例如 T.matrix[i, j] 而不仅仅是 T.matrix,因为这将在每次迭代时覆盖 T.matrix。

    closest.point <- function(M, y) {
      k <- nrow(M)
      m <- ncol(M)
      T.matrix <- matrix(nrow = k, ncol = m)
    
      for (i in 1:k) {
        for (j in 1:m) {
          T.matrix[i, j] <- (M[i,j] - y[j])^2 + (M[i,j] - y[j])^2
        }
      }
      W <- rowSums(T.matrix)
      return(which.min(W))
    }
    
    # example 1
    closest.point(M = rbind(c(1, 1, 1), 
                            c(1, 2, 5)), 
                  y = cbind(c(1, 2, 5)))
    # [1] 2
    
    # example 2
    closest.point(M = rbind(c(1, 1, 1, 1), 
                            c(1, 2, 5, 7)), 
                  y = cbind(c(2, 2, 6, 2)))
    # [1] 2
    

    【讨论】:

    • 谢谢,我同意其他解决方案更简洁,但这确实有助于我理解为什么我的未定义变量等不起作用。
    【解决方案2】:

    您应该尽量避免使用for 循环对向量和矩阵进行运算。 dist 基本函数计算距离。然后which.min会给你最小距离的索引。

    set.seed(0)
    M <- matrix(rnorm(100), ncol = 5)
    y <- rnorm(5)
    
    closest_point <- function(M, y) {
        dist_mat <- as.matrix(dist(rbind(M, y)))
        all_distances <- dist_mat[1:nrow(M),ncol(dist_mat)]
        which.min(all_distances)
    }
    
    closest_point(M, y)
    #>    
    #> 14
    

    reprex package (v2.0.1) 于 2021 年 12 月 10 日创建

    希望这是有道理的,如果您有任何问题,请告诉我。

    【讨论】:

    • 这更整洁 - 非常感谢。
    【解决方案3】:

    这里有很多问题

    1. p 已定义但从未使用过。
    2. 虽然没有错,但 T 不一定是矩阵。让它成为一个向量就足够了。
    3. 虽然使用 T 作为变量是危险的,但没有错,因为 T 也意味着 TRUE。
    4. 代码定义了 T,然后在下一条语句中立即将其丢弃,并覆盖它。从未使用过定义 T 的先前语句。
    5. for 的值始终为 NULL,因此将其分配给 T 毫无意义。
    6. 双 for 循环不执行任何操作。其中没有分配,因此循环无效。
    7. 循环指的是 m、n、X 和 x,但这些都没有定义。
    8. (X[i,j] - x[j])^2 重复。只需要一次。
    9. 在一行上单独写入 max(W) 无效。如果直接在控制台中完成,它只会导致打印完成。如果在函数中完成,则没有效果。如果您打算打印它,请编写 print(max(W))。
    10. 我们想要最近的点,而不是最远的点,所以 max 应该是 min。
    11. df 用在最后一行,但没有在任何地方定义。
    12. 没有测试运行,问题是不完整的。

    我已尝试进行最少的更改以使其正常工作:

    closest.point <- function(M, y) {
      nr <- nrow(M)
      nc <- ncol(M)
      W <- numeric(nr)  # vector having nr zeros
      for(i in 1:nr) {
        for(j in 1:nc) {
          W[i] <- W[i] + (M[i,j] - y[j])^2
        }
       }
      print(W)
      print(min(W))
      M[which.min(W),]
    }
    
    set.seed(123)
    M <- matrix(rnorm(12), 4); M
    ##             [,1]       [,2]       [,3]
    ## [1,] -0.56047565  0.1292877 -0.6868529
    ## [2,] -0.23017749  1.7150650 -0.4456620
    ## [3,]  1.55870831  0.4609162  1.2240818
    ## [4,]  0.07050839 -1.2650612  0.3598138
    
    y <- rnorm(3); y
    ## [1]  0.4007715  0.1106827 -0.5558411
    
    closest.point(M, y)
    ## [1] 0.9415062 2.9842785 4.6316069 2.8401691  <--- W
    ## [1] 0.9415062    <--- min(W)
    ## [1] -0.5604756  0.1292877 -0.6868529  <-- closest row
    

    也就是说,最近行的计算可以在这个函数中用一行来完成。我们转置 M,然后从中减去 y,这将从每列中减去 y,但转置的列是 M 的行,因此从每一行中减去 y。然后取平方差的列总和,找出哪个最小。使用那个下标M。

    closest.point2 <- function(M, y) { 
      M[which.min(colSums((t(M) - y)^2)), ]
    }
    
    closest.point2(M, y)
    ## [1] -0.5604756  0.1292877 -0.6868529  <-- closest row
    

    【讨论】:

    • 谢谢 - 问题列表真的很有帮助。
    猜你喜欢
    • 2015-12-17
    • 2023-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多