[英]Replacing entries in a numpy array with their quantile index with python
I have a one-dimensional numpy array with numbers, and I want each number replaced with the index of the quantile it belongs to. 我有一个带有数字的一维numpy数组,我希望每个数字都替换为它所属的分位数的索引。
This is my code for quintile indices: 这是我的五分类指数代码:
import numpy as np
def get_quintile_indices( a ):
result = np.ones( a.shape[ 0 ] ) * 4
quintiles = [
np.percentile( a, 20 ),
np.percentile( a, 40 ),
np.percentile( a, 60 ),
np.percentile( a, 80 )
]
for q in quintiles:
result -= np.less_equal( a, q ) * 1
return result
a = np.array( [ 58, 54, 98, 76, 35, 13, 62, 18, 62, 97, 44, 43 ] )
print get_quintile_indices( a )
Output: 输出:
[ 2. 2. 4. 4. 0. 0. 3. 0. 3. 4. 1. 1.]
You see I start with an array initialized with the highest possible index and for every quintile cutpoint substract 1 from each entry that is less or equal than the quintile cutpoint. 您会看到我从一个初始化为最高可能索引的数组开始,并且每个条目的每个五分位数cutract 1都小于或等于五分位数。 Is there a better way to do this? 有一个更好的方法吗? A build-in function that can be used to map numbers against a list of cutpoints? 内置函数,可用于将数字映射到切割点列表?
First off, we can generate those quintiles
in one go - 首先,我们可以一次性生成这些quintiles
-
quintiles = np.percentile( a, [20,40,60,80] )
For the final step to get the offsets, we can simply use np.searchsorted
and this might be the built-in you were looking for, like so - 对于获得偏移的最后一步,我们可以简单地使用np.searchsorted
,这可能是你正在寻找的内置,就像这样 -
out = np.searchsorted(quintiles, a)
Alternatively, a direct translation of your loopy code to a vectorized version would be with broadcasting
, like so - 或者,将循环代码直接转换为矢量化版本将使用broadcasting
,如此 -
# Use broadcasting to perform those comparisons in one go.
# Then, simply sum along the first axis and subtract from 4.
out = 4 - (quintiles[:,None] >= a).sum(0)
If quintiles
is a list, we need to assign it as an array and then use broadcasting
, like so - 如果quintiles
是一个列表,我们需要将其指定为数组,然后使用broadcasting
,如下所示 -
out = 4 - (np.asarray(quintiles)[:,None] >= a).sum(0)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.