8

我在 R 中有以下代码,它计算 Iris 数据集上的马氏距离并返回一个具有 150 个值的数值向量,一个用于数据集中的每个观察值。

x=read.csv("Iris Data.csv")
mean<-colMeans(x)
Sx<-cov(x)
D2<-mahalanobis(x,mean,Sx)  

我尝试使用'scipy.spatial.distance.mahalanobis(u, v, VI)'函数在Python中实现相同的功能,但似乎这个函数只接受一维数组作为参数。

4

2 回答 2

8

我使用了 R 中的 Iris 数据集,我想它与您使用的相同。

首先,这是我的 R 基准,用于比较:

x <- read.csv("IrisData.csv")
x <- x[,c(2,3,4,5)]
mean<-colMeans(x)
Sx<-cov(x)
D2<-mahalanobis(x,mean,Sx)  

然后,在 python 中你可以使用:

from scipy.spatial.distance import mahalanobis
import scipy as sp
import pandas as pd

x = pd.read_csv('IrisData.csv')
x = x.ix[:,1:]

Sx = x.cov().values
Sx = sp.linalg.inv(Sx)

mean = x.mean().values

def mahalanobisR(X,meanCol,IC):
    m = []
    for i in range(X.shape[0]):
        m.append(mahalanobis(X.iloc[i,:],meanCol,IC) ** 2)
    return(m)

mR = mahalanobisR(x,mean,Sx)

我定义了一个函数,以便您可以在其他集合中使用它,(注意我使用 pandas DataFrames 作为输入)

比较结果:

在 R 中

> D2[c(1,2,3,4,5)]

[1] 2.134468 2.849119 2.081339 2.452382 2.462155

在 Python 中:

In [43]: mR[0:5]
Out[45]: 
[2.1344679233248431,
 2.8491186861585733,
 2.0813386639577991,
 2.4523816316796712,
 2.4621545347140477]

请注意,您在 R 中得到的是平方马氏距离。

于 2015-04-23T13:08:47.763 回答
0

一个更简单的解决方案是:

from scipy.spatial.distance import cdist

x = ...

mean = x.mean(axis=0).reshape(1, -1)  # make sure 2D
vi = np.linalg.inv(np.cov(x.T))

cdist(mean, x, 'mahalanobis', VI=vi)
于 2018-07-05T00:42:29.053 回答