【问题标题】:Speed up of the calculation of the sum the point-wise difference in R加快计算 R 中逐点差的总和
【发布时间】:2020-02-02 06:51:09
【问题描述】:

假设我有两个数据集。第一个是:

t1<-sample(1:10,10,replace = T)
t2<-sample(1:10,10,replace = T)
t3<-sample(1:10,10,replace = T)
t4<-sample(11:20,10,replace = T)
t5<-sample(11:20,10,replace = T)
xtrain<-rbind(t1,t2,t3,t4,t5)
xtrain
   [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
t1    7    3    9   10    4    9    2    1    6     9
t2    5    1    1    6    5    3   10    2    6     3
t3    8    6    9    7    9    2    3    5    1     8
t4   16   18   14   17   19   20   15   15   20    19
t5   13   14   18   13   11   19   13   17   16    14

第二个是:

t6<-sample(1:10,10,replace = T)
t7<-sample(11:20,10,replace = T)
xtest<-rbind(t6,t7)
xtest
   [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
t6    1    5    8    2   10    2    3    4    8     5
t7   14   18   15   12   17   20   17   13   16    17

我想做的是计算xtest的每一行和xtrain的每一行之间的距离之和。例如:

sum((7-1)^2+(3-5)^2+(9-8)^2+.....(9-5)^2)
sum((5-1)^2+(1-5)^2+(1-8)^2+.....(4-5)^2)
...
sum((14-13)^2+(18-14)^2+(15-18)^2+.....(17-14)^2) 

我目前拥有的是使用两个 for 循环(见下文),我认为这不能处理大型数据集:

sumPD<-function(vector1,vector2){
  sumPD1<-sum((vector1-vector2)^2)
  return(sumPD1)
}
loc<-matrix(NA,nrow=dim(xtrain)[1],ncol=dim(xtest)[1])
for(j in 1:dim(xtest)[1]){    
  for(i in 1:dim(xtrain)[1]){
     loc[i,j]<-sumPD(xtrain[i,],xtest[j,])
   }
 }

我想请教有关如何修改代码以提高效率的建议。先感谢您!希望有好的讨论!

【问题讨论】:

    标签: r matrix euclidean-distance computation pairwise-distance


    【解决方案1】:

    一个选项是outer

    f1 <- Vectorize(function(i, j) sumPD(xtrain[i,], xtest[j,]))
    loc2 <- outer(seq_len(nrow(xtrain)), seq_len(nrow(xtest)), f1)
    identical(loc, loc2)
    #[1] TRUE
    

    【讨论】:

      【解决方案2】:

      rdist 包具有快速计算这些成对距离的功能:

      rdist::cdist(xtrain, xtest)^2
      

      输出:

           [,1] [,2]
      [1,]   65 1029
      [2,]   94 1324
      [3,]  165 1103
      [4,] 1189  213
      [5,] 1271  191
      

      【讨论】:

        【解决方案3】:

        这里有两种简单的方法。

        使用dist - 将计算比需要更多的距离:

        dists <- as.matrix(dist(rbind(xtrain, xtest))^2)
        dists <- dists[rownames(xtrain), rownames(xtest)]
        dists
             t6   t7
        t1  140 1179
        t2  134  693
        t3  119  974
        t4 1028   91
        t5 1085   44
        

        使用适用于 X 矩阵和 y 向量的简单自定义函数:

        euclid <- function(X,y) colSums((X-y)^2)
        dists  <- mapply(euclid, list(t(xtrain)), split(xtest, row(xtest)))
        dists
           [,1] [,2]
        t1  140 1179
        t2  134  693
        t3  119  974
        t4 1028   91
        t5 1085   44
        

        【讨论】:

          【解决方案4】:

          你可以转置你的矩阵,使用向量差分和一个循环:

          ftrain <- t(xtrain)
          ftest <- t(xtest)
          
          
          sapply(1:(dim(ftest)[2]),function(i){
            colSums((ftrain - ftest[,i])^2)
          })
          
          
             [,1] [,2]
          t1  103 1182
          t2  125 1262
          t3  130 1121
          t4 1478  159
          t5 1329  142
          

          colSums 相当高效,但如果您想要更快的速度,请查看there

          【讨论】:

          • 我认为您可以使用ntrain = nrow(xtrain); ntest = nrow(xtest); matrix(rowSums( (xtrain[rep(1:ntrain, ntest), ] - xtest[rep(1:ntest, each=ntrain),])^2), nc=ntest) 避免循环,尽管您的意图更清晰
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-11-13
          • 1970-01-01
          • 1970-01-01
          • 2023-03-03
          • 2019-11-15
          • 1970-01-01
          相关资源
          最近更新 更多