计算每个元素相对于其列的百分位数

时间:2014-08-20 12:27:27

标签: python numpy scipy

所以我的NumPy数组看起来像这样

npfinal = 
    [[1, 3, 5, 0, 0, 0],
    [5, 2, 4, 0, 0, 0],
    [7, 7, 2, 0, 0, 0],
    .
    .
    .

我使用的样本数据集是25k行。

前3列包含有意义的数据,其余是百分位数的占位符。

所以我需要相对于[0] [3]中的整个第一列的[0] [0] 的百分位数。因此,[1,5,7,...]

栏中的1%百分位数得分

我的第一次尝试是:

import scipy.stats as ss
...
numofcols = 3
for row in npfinal:
    for i in range(0,numofcols):
        row[i+numofcols] = int(round(ss.percentileofscore(npfinal[:,i], row[i])))

但这花费了太多时间;并且在完整的数据集上它是不可能的。

我对这些大型数据集的计算世界不熟悉,因此我们将不胜感激。

2 个答案:

答案 0 :(得分:1)

您可以通过对数组进行排序并将结果索引除以行总数来计算百分位数(假设NumPy可用):

import numpy as np

M = np.array([[1, 3, 5], [5, 2, 4], [7, 7, 2]])

percentile = np.argsort(np.argsort(M, axis=0), axis=0) / float(len(M)) * 100

print "M:\n", M
print "percentile:\n", percentile

输出:

M:
[[1 3 5]
 [5 2 4]
 [7 7 2]]
percentile:
[[  0.          33.33333333  66.66666667]
 [ 33.33333333   0.          33.33333333]
 [ 66.66666667  66.66666667   0.        ]]

现在你只需要连接结果和原始数组。

答案 1 :(得分:1)

我找到了一个解决方案,我相信当数组中存在重复值时它会更好:

import numpy as np
from scipy import stats

# some array with repeated values:
M = np.array([[1, 7, 2], [5, 2, 2], [5, 7, 2]])    

# calculate percentiles applying scipy rankdata to each column:
percentile = np.apply_along_axis(sp.stats.rankdata, 0, M, method='average')/len(M)

np.argsort解决方案存在的问题是它为相同值的重复提供了不同的百分位数。例如,如果你有:

percentile_argsort = np.argsort(np.argsort(M, axis=0), axis=0) / float(len(M)) * 100
percentile_rankdata = np.apply_along_axis(sp.stats.rankdata, 0, M, method='average')/len(M)

两种不同的方法将输出结果:

M
array([[1, 7, 2],
       [5, 2, 2],
       [5, 7, 2]])
percentile_argsort
array([[  0.        ,  33.33333333,   0.        ],
       [ 33.33333333,   0.        ,  33.33333333],
       [ 66.66666667,  66.66666667,  66.66666667]])
percentile_rankdata
array([[ 0.33333333,  0.83333333,  0.66666667],
       [ 0.83333333,  0.33333333,  0.66666667],
       [ 0.83333333,  0.83333333,  0.66666667]])