2

データセットの各観測間のマハラノビス距離を計算しようとしてdatいます。各行は観測であり、各列は変数です。このような距離は次のように定義されます。

方式

それを行う関数を書きましたが、遅いように感じます。R でこれを計算するより良い方法はありますか?

関数をテストするためのデータを生成するには:

generateData <- function(nObs, nVar){
  library(MASS)
  mvrnorm(n=nObs, rep(0,nVar), diag(nVar))
  }

これまで書いてきた機能です。どちらも機能し、私のデータ (800 個の obs と 90 個の変数) の場合、method = "forLoop"method = "apply"でそれぞれ約 30 秒と 33 秒かかります。

mhbd_calc2 <- function(dat, method) { #Method is either "forLoop" or "apply"
  dat <- as.matrix(na.omit(dat))
  nObs <- nrow(dat)
  mhbd <- matrix(nrow=nObs,ncol = nObs)
  cv_mat_inv = solve(var(dat))

  distMH = function(x){  #Mahalanobis distance function
    diff = dat[x[1],]-dat[x[2],]
    diff %*% cv_mat_inv %*% diff
  }

  if(method=="forLoop")
  {
    for (i in 1:nObs){
      for(j in 1:i){
        mhbd[i,j] <- distMH(c(i,j))
      }
    }
  }
  if(method=="apply")
  {
    mhbd[lower.tri(mhbd)] = apply(combn(nrow(dat),2),2, distMH)
  }
  result = sqrt(mhbd)
  colnames(result)=rownames(dat)
  rownames(result)=rownames(dat)
  return(as.dist(result))
}

NB: 使ってみouter()ましたが、さらに遅くなりました (60 秒)

4

1 に答える 1

3

数学の知識が必要です。

  1. 経験的共分散のコレスキー分解を行い、観測値を標準化します。
  2. dist変換された観測値のユークリッド距離を計算するために使用します。

dist.maha <- function (dat) {
  X <- as.matrix(na.omit(dat))  ## ensure a valid matrix
  V <- cov(X)  ## empirical covariance; positive definite
  L <- t(chol(V))  ## lower triangular factor
  stdX <- t(forwardsolve(L, t(X)))  ## standardization
  dist(stdX)  ## use `dist`
  }

set.seed(0)
x <- matrix(rnorm(6 * 3), 6, 3)

dist.maha(x)
#         1        2        3        4        5
#2 2.362109                                    
#3 1.725084 1.495655                           
#4 2.959946 2.715641 2.690788                  
#5 3.044610 1.218184 1.531026 2.717390         
#6 2.740958 1.694767 2.877993 2.978265 2.794879

結果はあなたと一致しますmhbd_calc2

于 2016-12-07T19:34:52.000 に答える