NumPy百分位函数与MATLAB的百分位函数不同

时间:2014-07-15 17:56:31

标签: python r matlab numpy percentile

当我尝试在MATLAB中计算第75个百分点时,我获得的值与NumPy中的值不同。

MATLAB:

>> x = [ 11.308 ;   7.2896;   7.548 ;  11.325 ;   5.7822;   9.6343;
     7.7117;   7.3341;  10.398 ;   6.9675;  10.607 ;  13.125 ;
     7.819 ;   8.649 ;   8.3106;  12.129 ;  12.406 ;  10.935 ;
    12.544 ;   8.177 ]

>> prctile(x, 75)

ans =

11.3165

Python + NumPy:

>>> import numpy as np

>>> x = np.array([ 11.308 ,   7.2896,   7.548 ,  11.325 ,   5.7822,   9.6343,
     7.7117,   7.3341,  10.398 ,   6.9675,  10.607 ,  13.125 ,
     7.819 ,   8.649 ,   8.3106,  12.129 ,  12.406 ,  10.935 ,
    12.544 ,   8.177 ])

>>> np.percentile(x, 75)
11.312249999999999

我也用R检查了答案,我得到了NumPy的答案。

R:

> x <- c(11.308 ,   7.2896,   7.548 ,  11.325 ,   5.7822,   9.6343,
+          7.7117,   7.3341,  10.398 ,   6.9675,  10.607 ,  13.125 ,
+          7.819 ,   8.649 ,   8.3106,  12.129 ,  12.406 ,  10.935 ,
+         12.544 ,   8.177)
> quantile(x, 0.75)
     75% 
11.31225 

这里发生了什么?是否有任何方法可以使Python&amp; R的行为反映了MATLAB的?

2 个答案:

答案 0 :(得分:10)

MATLAB显然默认使用中点插值。 NumPy和R默认使用线性插值:

In [182]: np.percentile(x, 75, interpolation='linear')
Out[182]: 11.312249999999999

In [183]: np.percentile(x, 75, interpolation='midpoint')
Out[183]: 11.3165

了解linearmidpoint之间的区别,请考虑以下简单示例:

In [187]: np.percentile([0, 100], 75, interpolation='linear')
Out[187]: 75.0

In [188]: np.percentile([0, 100], 75, interpolation='midpoint')
Out[188]: 50.0

编译最新版本的NumPy(使用Ubuntu):

mkdir $HOME/src
git clone https://github.com/numpy/numpy.git
git remote add upstream https://github.com/numpy/numpy.git
# Read ~/src/numpy/INSTALL.txt
sudo apt-get install libatlas-base-dev libatlas3gf-base
python setup.py build --fcompiler=gnu95
python setup.py install

使用git代替pip的好处是,升级(或降级)到其他版本的NumPy非常容易(并且您也获得了源代码):

git fetch upstream
git checkout master # or checkout any other version of NumPy
cd ~/src/numpy
/bin/rm -rf build
cdsitepackages    # assuming you are using virtualenv; otherwise cd to your local python sitepackages directory
/bin/rm -rf numpy numpy-*-py2.7.egg-info
cd ~/src/numpy
python setup.py build --fcompiler=gnu95
python setup.py install

答案 1 :(得分:6)

由于即使在@ cpaulik的评论之后接受的答案仍然不完整,我在这里发布的是希望更完整的答案(尽管为了简洁起见,但并不完美,见下文)。

使用np.percentile(x,p,interpolation ='midpoint')只能为非常具体的值给出相同的答案,即当p / 100是1 / n的倍数时,n是元素的数量数组。在最初的问题中,情况确实如此,因为n = 20且p = 75,但一般来说这两个函数不同。

Matlab的prctile函数的简短模拟由下式给出:

def quantile(x,q):
    n = len(x)
    y = np.sort(x)
    return(np.interp(q, np.linspace(1/(2*n), (2*n-1)/(2*n), n), y))

def prctile(x,p):
    return(quantile(x,np.array(p)/100))

这个函数,就像Matlab的函数一样,给出了从min(x)到max(x)的分段线性输出。 Numpy的百分位函数,插值=中点,返回两个最小元素的平均值和两个最大元素的平均值之间的分段常数函数。在原始问题中绘制数组的两个函数给出了the picture in this link (抱歉无法嵌入它)。红色虚线表示75%的百分位数,两个函数实际上重合。

P.S。这个函数实际上并不等同于Matlab的原因是它只接受一维x,给出了更高维度的东西的错误。另一方面,Matlab的一个接受更高的暗淡x并在第一个(非平凡的)维度上运行,但正确实现它可能需要更长的时间。但是,这个和Matlab的函数都应该正确地用于p / q的更高维度输入(这要归功于使用np.interp来处理它)。