如何在 python 中计算马氏距离
马哈拉诺比斯距离是多元空间中两点之间的距离。它通常用于检测涉及多个变量的统计分析中的异常值。
本教程介绍如何在 Python 中计算马哈拉诺比斯距离。
示例:Python 中的马哈拉诺比斯距离
使用以下步骤计算 Python 数据集中每个观测值的马氏距离。
步骤 1:创建数据集。
首先,我们将创建一个数据集,显示 20 名学生的考试成绩,以及他们学习所用的小时数、参加的模拟考试次数以及他们当前课程的成绩:
import numpy as np import pandas as pd import scipy as stats data = {'score': [91, 93, 72, 87, 86, 73, 68, 87, 78, 99, 95, 76, 84, 96, 76, 80, 83, 84, 73, 74], 'hours': [16, 6, 3, 1, 2, 3, 2, 5, 2, 5, 2, 3, 4, 3, 3, 3, 4, 3, 4, 4], 'prep': [3, 4, 0, 3, 4, 0, 1, 2, 1, 2, 3, 3, 3, 2, 2, 2, 3, 3, 2, 2], 'grade': [70, 88, 80, 83, 88, 84, 78, 94, 90, 93, 89, 82, 95, 94, 81, 93, 93, 90, 89, 89] } df = pd.DataFrame(data,columns=['score', 'hours', 'prep','grade']) df.head() score hours prep grade 0 91 16 3 70 1 93 6 4 88 2 72 3 0 80 3 87 1 3 83 4 86 2 4 88
步骤 2:计算每个观测值的马氏距离。
接下来,我们将编写一个简短的函数来计算马氏距离。
#create function to calculate Mahalanobis distance def mahalanobis(x= None , data= None , cov= None ): x_mu = x - np.mean(data) if not cov: cov = np.cov(data.values.T) inv_covmat = np.linalg.inv(cov) left = np.dot(x_mu, inv_covmat) mahal = np.dot(left, x_mu.T) return mahal.diagonal() #create new column in dataframe that contains Mahalanobis distance for each row df['mahalanobis'] = mahalanobis(x=df, data=df[['score', 'hours', 'prep', 'grade']]) #display first five rows of dataframe df.head() score hours prep grade mahalanobis 0 91 16 3 70 16.501963 1 93 6 4 88 2.639286 2 72 3 0 80 4.850797 3 87 1 3 83 5.201261 4 86 2 4 88 3.828734
步骤 3:计算每个马哈拉诺比斯距离的 p 值。
我们可以看到一些马哈拉诺比斯距离比其他距离大得多。为了确定任何距离是否具有统计显着性,我们需要计算它们的 p 值。
每个距离的 p 值计算为与具有 k-1 自由度的 Mahalanobis 距离的卡方统计量相对应的 p 值,其中 k = 变量数。因此在本例中我们将使用自由度 4-1 = 3。
from scipy.stats import chi2 #calculate p-value for each mahalanobis distance df['p'] = 1 - chi2.cdf(df['mahalanobis'], 3) #display p-values for first five rows in dataframe df.head() score hours prep grade mahalanobis p 0 91 16 3 70 16.501963 0.000895 1 93 6 4 88 2.639286 0.450644 2 72 3 0 80 4.850797 0.183054 3 87 1 3 83 5.201261 0.157639 4 86 2 4 88 3.828734 0.280562
通常,小于 0.001 的p 值被视为异常值。我们可以看到第一个观测值是数据集中的异常值,因为它的 p 值小于 0.001。
根据问题的上下文,您可能决定从数据集中删除此观察值,因为它是异常值,可能会影响分析结果。