Jam*_*mes 9 python matlab numpy r 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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
我也用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
Run Code Online (Sandbox Code Playgroud)
这里发生了什么?有没有办法使Python和R的行为镜像MATLAB?
unu*_*tbu 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
Run Code Online (Sandbox Code Playgroud)
该明白之间的差别linear,并midpoint考虑这个简单的例子:
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
Run Code Online (Sandbox Code Playgroud)
要编译最新版本的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
Run Code Online (Sandbox Code Playgroud)
使用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
Run Code Online (Sandbox Code Playgroud)
由于即使在@ 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))
Run Code Online (Sandbox Code Playgroud)
该函数与Matlab一样,给出了从min(x)到max(x)的分段线性输出.Numpy的百分位函数,插值=中点,返回两个最小元素的平均值和两个最大元素的平均值之间的分段常数函数.在原始问题中绘制数组的两个函数会给出此链接中的图片(抱歉无法嵌入).红色虚线表示75%的百分位数,其中两个函数实际上重合.
PS这个函数实际上并不等同于Matlab的原因是它只接受一维x,给更高维度的东西带来错误.另一方面,Matlab的一个接受更高的暗淡x并在第一个(非平凡的)维度上运行,但正确实现它可能需要更长的时间.但是,这个和Matlab的函数都应该正确地用于p/q的更高维度输入(由于使用np.interp来处理它).