8

パッケージ StatMatch ( http://cran.r-project.org/web/packages/StatMatch/StatMatch.pdf ) で mahalanobis.dist 関数を見つけましたが、私が望んでいることを正確に実行していません。data.y の各観測値から data.x の各観測値までのマハラノビス距離を計算しているようです。

data.y の 1 つの観測値から data.x のすべての観測値までのマハラノビス距離を計算したいと思います。それが理にかなっている場合、基本的に、1つのポイントからポイントの「クラウド」までのマハラノビス距離を計算します。観測が別の観測グループの一部である確率のアイデアを得る

この人 ( http://people.revoledu.com/kardi/tutorial/Similarity/MahalanobisDistance.html ) はこれを行っているようで、R で彼のプロセスを再現しようとしましたが、下部に到達すると失敗します方程式の:

mahaldist = sqrt((inversepooledcov %*% t(meandiffmatrix)) %*% meandiffmatrix)

私が使用しているすべてのコードは次のとおりです。

a = rbind(c(2,2), c(2,5), c(6,5),c(7,3))

colnames(a) = c('x', 'y')

b = rbind(c(6,5),c(3,4))

colnames(b) = c('x', 'y')

acov = cov(a)
bcov = cov(b)

meandiff1 = mean(a[,1]) - mean(b[,1])

meandiff2 = mean(a[,2]) - mean(b[,2])

meandiffmatrix = rbind(c(meandiff1,meandiff2))

totaldata = dim(a)[1] + dim(b)[1]

pooledcov = (dim(a)[1]/totaldata * acov) + (dim(b)[1]/totaldata * bcov)

inversepooledcov = solve(pooledcov)

mahaldist = sqrt((inversepooledcov %*% t(meandiffmatrix)) %*% meandiffmatrix)
4

7 に答える 7

5

あなたが見たのと同じウェブサイトからこれを試してみたところ、この質問に出くわしました。スクリプトを動作させることができましたが、別の結果が得られました。

#WORKING EXAMPLE
#MAHALANOBIS DIST OF TWO MATRICES

#define matrix
mat1<-matrix(data=c(2,2,6,7,4,6,5,4,2,1,2,5,5,3,7,4,3,6,5,3),nrow=10)
mat2<-matrix(data=c(6,7,8,5,5,5,4,7,6,4),nrow=5)
#center data
mat1.1<-scale(mat1,center=T,scale=F)
mat2.1<-scale(mat2,center=T,scale=F)
#cov matrix
mat1.2<-cov(mat1.1,method="pearson")
mat2.2<-cov(mat2.1,method="pearson")
n1<-nrow(mat1)
n2<-nrow(mat2)
n3<-n1+n2
#pooled matrix
mat3<-((n1/n3)*mat1.2) + ((n2/n3)*mat2.2)
#inverse pooled matrix
mat4<-solve(mat3)
#mean diff
mat5<-as.matrix((colMeans(mat1)-colMeans(mat2)))
#multiply
mat6<-t(mat5) %*% mat4
#multiply
sqrt(mat6 %*% mat5)

mahalanobis()この関数は、1 つのマトリックス内の個体 (行) 間のマハラノビス距離を計算するために使用されると思います。の関数pairwise.mahalanobis()package(HDMD)、2 つ以上の行列を比較して、行列間のマハラノビス距離を与えることができます。

于 2013-11-27T09:05:36.320 に答える
5

パッケージmahalanobis内の関数を使用するのはどうですか:stats

 mahalanobis(x, center, cov, inverted = FALSE, ...)
于 2013-09-06T13:40:45.420 に答える
2

次のように関数stats::mahalanobisをラップして、マハラノビス距離行列 (ペアごとのマハラノビス距離) を出力できます。

# x - data frame
# cx - covariance matrix; if not provided, 
#      it will be estimated from the data
mah <- function(x, cx = NULL) {
  if(is.null(cx)) cx <- cov(x)
  out <- lapply(1:nrow(x), function(i) {
    mahalanobis(x = x, 
                center = do.call("c", x[i, ]),
                cov = cx)
  })
  return(as.dist(do.call("rbind", out)))
}

次に、データをクラスター化してプロットできます。次に例を示します。

# Dummy data
x <- data.frame(X = c(rnorm(10, 0), rnorm(10, 5)), 
                Y = c(rnorm(10, 0), rnorm(10, 7)), 
                Z = c(rnorm(10, 0), rnorm(10, 12)))
rownames(x) <- LETTERS[1:20]
plot(x, pch = LETTERS[1:20])

ここに画像の説明を入力

# Comute the mahalanobis distance matrix
d <- mah(x)
d

# Cluster and plot
hc <- hclust(d)
plot(hc)

ここに画像の説明を入力

于 2015-12-07T22:27:27.963 に答える
1

平方根を取る前の出力は次のとおりです。

inversepooledcov %*% t(meandiffmatrix) %*% meandiffmatrix
          [,1]        [,2]
x -0.004349227 -0.01304768
y  0.114529639  0.34358892

負の数の平方根を取ることができると思うのでNAN、負の要素があります:

 sqrt(inversepooledcov %*% t(meandiffmatrix) %*% meandiffmatrix)
       [,1]      [,2]
x       NaN       NaN
y 0.3384223 0.5861646

Warning message:
In sqrt(inversepooledcov %*% t(meandiffmatrix) %*% meandiffmatrix) :
  NaNs produced
于 2013-09-06T13:38:38.197 に答える
1

共分散行列が恒等行列の場合、マハラノビス距離は (二乗) ユークリッド距離と同等です。変数間に共分散がある場合、最初に行列をホワイトニングして共分散を除去することにより、マハラノビスと平方ユークリッドを等しくすることができます。つまり、次のことを行います。

#X is your matrix
if (!require("whitening")) install.packages("whitening")

X <- whitening::whiten(X) # default is ZCA (Mahalanobis) whitening
X_dist <- dist(X, diag = T, method = "euclidean")^2

これにより、以前の回答の 1 つで Davit が提供したコードと同じ距離行列が得られることが確認できます。

于 2019-12-12T21:07:55.160 に答える