在R

时间:2018-10-11 05:02:03

标签: r distance-matrix

我的任务是基于自定义的距离度量创建距离矩阵函数。 距离量度如下:

wabs_dist = function(u, v, w){
   return( sum((abs(u-v))*w) )
}

其中u和v是向量,w是权重。

我要解决的问题:

我要创建一个距离矩阵函数create-dm(x,w),通过为所有对象对a和a调用wabs-dist(a,b,w)来返回数据帧x中对象的距离矩阵。 b属于x。如果x是具有4个属性的数据集,则w是向量,例如w = c(1,1,3,2)分配给每个属性。是的,已经有像dist()这样的标准函数,但是我要在这里使用wabs_dist创建自己的函数。

到目前为止,我的解决方案是

create_dm = function(x, w){ #x is a dataframe
distances = matrix(0, nrow = nrow(x), ncol = nrow(x))
for (i in 1:nrow(x)) {
 for(j in 1:(i-1)){
     distances[i, j] = wabs_dist(x[i,], x[j,], w)
     distances[j, i] = distances[i, j]
   }
}
 return(distances)  
}

我如何实现权重向量,因为我本着编写仅传递一个权重的思想来编写此函数的方法,但是现在我必须编写它才能接受列表。如何使用权重列表实现此功能?

此功能需要大量时间才能运行。实际上,它从未真正打印出距离矩阵函数。我不知道为什么

一个例子:

让x为包含向量a,b和c的数据帧,其中: 答:(1、2) b:(4、5) c:(9,12)

w是权重向量:(0.2,0.3)

wabs-dist(a,b,w)= 1.5 wabs-dist(b,c,w)= 3.1

create-dm(x,w)=

0     1.5   4.6

1.5   0     3.1

4.6   3.1   0

1 个答案:

答案 0 :(得分:1)

我最近有一个类似的问题。我的最终解决方案是使用Rcpp软件包用C ++编写它。将此代码另存为dmat.cpp

#include <Rcpp.h>

using namespace Rcpp;


// [[Rcpp::export]]
NumericMatrix dmat(NumericMatrix x, NumericVector w) {
  int n = x.nrow();
  NumericMatrix d = no_init_matrix(n, n);

  for(int i=0; i<n;i++){
    for(int j=i+1; j<n;j++){
      d(i,j)=sum(w*abs((x(i,_)-x(j,_))));
      d(j,i)=d(i,j);
    }

    d(i,i)=0;

  }
  return d;
}

然后安装并加载软件包“ Rcpp”,并使用sourceCpp()加载该功能。之后,您可以像使用其他任何R函数一样使用它

library(Rcpp)
sourceCpp("path/to/file/dmat.cpp")

x <- matrix(rnorm(1500),ncol=3)
w <- 1:3

system.time(distR <- create_dm(x,w))
       User      System verstrichen 
   1.81        0.02        1.84 

system.time(distCpp <- dmat(x,w))
       User      System verstrichen 
      0           0           0

identical(round(distR,10), round(distCpp,10))
[1] TRUE

如果仅使用identical()而不四舍五入,则结果为FALSE。不知道为什么。也许可以由其他人回答。

如果可以使用欧几里德距离而不是绝对距离,则可以使用软件包apcluster。这是我的第一个解决方案。但是C ++解决方案仍然更快。