R 函数中的矩阵计算

Posted

技术标签:

【中文标题】R 函数中的矩阵计算【英文标题】:Matrix calculations within an R function 【发布时间】: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),]

【问题讨论】:

【参考方案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】:

这里有很多问题

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

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

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

【讨论】:

谢谢 - 问题列表真的很有帮助。

以上是关于R 函数中的矩阵计算的主要内容,如果未能解决你的问题,请参考以下文章

R语言使用kernlab包中的ksvm函数构建支持向量机SVM模型(Support vector machines)使用RBF核函数使用table函数计算混淆矩阵评估分类模型性能

R语言(数值列表矩阵)上应用函数(sqrtroundmeanlog)将矩阵所有数据求对数就矩阵整体的均值使用apply函数计算矩阵matrix的行均值列均值trim设置返回结果精度

R语言(数值列表矩阵)上应用函数(sqrtroundmeanlog)将矩阵所有数据求对数就矩阵整体的均值使用apply函数计算矩阵matrix的行均值列均值trim设置返回结果精度

R语言使用party包中的cforest函数基于条件推理决策树(Conditional inference trees)构建随机森林使用varimp函数查看特征重要度使用table函数计算混淆矩阵

R语言使用e1071包中的svm函数构建支持向量机SVM模型(Support vector machines)默认使用RBF核函数使用table函数计算混淆矩阵评估分类模型性能

R语言使用caret包的confusionMatrix函数计算混淆矩阵使用编写的自定义函数可视化混淆矩阵(confusion matrix)