计算每个元素相对于其列的百分位数分数
我的NumPy数组看起来是这样的:
npfinal =
[[1, 3, 5, 0, 0, 0],
[5, 2, 4, 0, 0, 0],
[7, 7, 2, 0, 0, 0],
.
.
.
我正在处理的样本数据集有25000行。
前3列包含有意义的数据,其余的列是用来放百分位数的占位符。
我需要计算a[0][0]在整个第一列中的百分位数,结果放在a[0][3]里。也就是说,1在列[1,5,7,...]中的百分位数得分。
我第一次尝试是:
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 个回答
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. ]]
现在你只需要把结果和原来的数组合并在一起就可以了。
2
我找到了一种解决方案,我觉得在数组中有重复值时效果更好:
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]])