在numpy中转换一组数字,以便将每个数字转换为一些小于它的其他数字

Pea*_*ful 8 python numpy python-3.x

考虑一组数字:

In [8]: import numpy as np

In [9]: x = np.array([np.random.random() for i in range(10)])

In [10]: x
Out[10]: 
array([ 0.62594394,  0.03255799,  0.7768568 ,  0.03050498,  0.01951657,
        0.04767246,  0.68038553,  0.60036203,  0.3617409 ,  0.80294355])
Run Code Online (Sandbox Code Playgroud)

现在,我想这组变换成另一组y以下列方式:每个元素ix,相应的元素jy将其他元素的数量在x这不到i.例如,上面给出的内容x如下:

In [25]: y
Out[25]: array([ 6.,  2.,  8.,  1.,  0.,  3.,  7.,  5.,  4.,  9.])
Run Code Online (Sandbox Code Playgroud)

现在,我可以使用简单的python循环来做到这一点:

In [16]: for i in range(len(x)):
    ...:     tot = 0
    ...:     for j in range(len(x)):
    ...:         if x[i] > x[j]: tot += 1
    ...:     y[i] = int(tot)
Run Code Online (Sandbox Code Playgroud)

但是,当长度x非常大时,代码变得非常慢.我想知道是否可以带来任何笨拙的魔法来拯救.例如,如果我必须过滤所有小于的元素0.5,我会简单地使用布尔屏蔽:

In [19]: z = x[x < 0.5]

In [20]: z
Out[20]: array([ 0.03255799,  0.03050498,  0.01951657,  0.04767246,  0.3617409 ])
Run Code Online (Sandbox Code Playgroud)

可以使用这样的东西,以便更快地实现同样的事情吗?

And*_*eak 11

您实际需要做的是获得数组排序顺序的反转:

import numpy as np
x = np.random.rand(10)
y = np.empty(x.size,dtype=np.int64)
y[x.argsort()] = np.arange(x.size)
Run Code Online (Sandbox Code Playgroud)

示例运行(在ipython中):

In [367]: x
Out[367]: 
array([ 0.09139335,  0.29084225,  0.43560987,  0.92334644,  0.09868977,
        0.90202354,  0.80905083,  0.4801967 ,  0.99086213,  0.00933582])

In [368]: y
Out[368]: array([1, 3, 4, 8, 2, 7, 6, 5, 9, 0])
Run Code Online (Sandbox Code Playgroud)

或者,如果要获得大于每个对应元素的元素数x,则必须将排序从升序转换为降序.一个可能的选择是简单地交换索引的构造:

y_rev = np.empty(x.size,dtype=np.int64)
y_rev[x.argsort()] = np.arange(x.size)[::-1]
Run Code Online (Sandbox Code Playgroud)

另外,正如@unutbu在评论中建议的那样,将原始数组映射到新数组:

y_rev = x.size - y - 1
Run Code Online (Sandbox Code Playgroud)


Div*_*kar 5

这是一种使用方法np.searchsorted-

np.searchsorted(np.sort(x),x)
Run Code Online (Sandbox Code Playgroud)

另一个主要基于@Andras Deak's solution使用argsort()-

x.argsort().argsort()
Run Code Online (Sandbox Code Playgroud)

样品运行 -

In [359]: x
Out[359]: 
array([ 0.62594394,  0.03255799,  0.7768568 ,  0.03050498,  0.01951657,
        0.04767246,  0.68038553,  0.60036203,  0.3617409 ,  0.80294355])

In [360]: np.searchsorted(np.sort(x),x)
Out[360]: array([6, 2, 8, 1, 0, 3, 7, 5, 4, 9])

In [361]: x.argsort().argsort()
Out[361]: array([6, 2, 8, 1, 0, 3, 7, 5, 4, 9])
Run Code Online (Sandbox Code Playgroud)