Python,Numpy,用1替换第二个最大值,用0替换其他值

时间:2017-09-07 14:12:23

标签: python numpy

探索互联网并没有给我带来任何问题的结果。我有这样的数组:

y=  [[ 2.63321579e-16   9.99986649e-01   2.90973702e-32   9.93230242e-06
        1.56965105e-30   1.63843623e-07   8.52455060e-22   0.00000000e+00
        5.65191413e-27   0.00000000e+00   3.20573202e-25   0.00000000e+00
        3.33013941e-06   0.00000000e+00   8.01929339e-22   2.14279644e-26
        0.00000000e+00   4.32979661e-08   1.01565330e-29   0.00000000e+00
        0.00000000e+00   4.52104604e-11]
     [  0.00000000e+00   1.57162935e-01   0.00000000e+00   0.00000000e+00
        0.00000000e+00   0.00000000e+00   0.00000000e+00   0.00000000e+00
        0.00000000e+00   8.42837036e-01   3.78666698e-08   0.00000000e+00
        0.00000000e+00   0.00000000e+00   0.00000000e+00   0.00000000e+00
        0.00000000e+00   0.00000000e+00   0.00000000e+00   0.00000000e+00
        0.00000000e+00   0.00000000e+00]]

我想要做的是用' 1'替换每行的第二个最大值。 ' 0'以及其他任何值。我知道如何使用max值,首先创建zeros_like数组,然后用1替换max值。所以对于这个方法是:

x = np.zeros_like(y)
x[np.arange(len(y)), y.argmax(1)] = 1

但是第二个最大值怎么样?期望的输出应该是:

y=  [[ 0 0 0 **1** 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]   
     [ 0 **1** 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]]

我可以获得第二个最大值,但替换它会导致我的问题。

2 个答案:

答案 0 :(得分:1)

首先要找到您要查找的元素,您可以使用argsort函数获取第二轴上每个向量的值的排序索引列表。

y = np.random.randn(2,10)
print(y)
sorted_idx = np.argsort(y, axis=1)
nth_element = 2 # Select the nth smallest element of each vector in the second dimension.
indexes = np.arange(y.shape[0]), np.argsort(y, axis=1)[:, nth_element]
answer = y[indexes]
print(answer)

如果您希望在每个向量中获取第n个最大元素,请使用nth_element = -2代替

此测试用例的结果将是:

[[ 2.31754087  1.02712883 -1.06811812  1.2073763  -0.06212109 -0.78401522
  -2.28638542 -0.82081567  1.16203424  0.2775298 ]
 [ 0.30816667  0.81606153  1.32791256  0.65654608  0.36659678  1.29219518
  -0.72793581  0.26714565 -0.69083268 -0.83825039]]

[-0.82081567 -0.69083268]

在此之后,您可以创建一个与初始矩阵具有相同形状的零矩阵,并将保存索引中的相同元素替换为其中的元素。

zeros = np.zeros(y.shape)
zeros[indexes] = y[indexes]
print(zeros)

返回

[[ 0.          0.          0.          0.          0.          0.          0.
  -0.82081567  0.          0.        ]
 [ 0.          0.          0.          0.          0.          0.          0.
   0.         -0.69083268  0.        ]]

答案 1 :(得分:1)

这是基于np.argpartition的一种方法。这是为了性能,因为它不需要对行中的所有元素进行排序,因为它只是分成由第n个最大元素位置分隔的两个部分。因此,np.argpartition(a,-n, axis=1)[:,-n]会为每行提供n-th最大元素位置。所以,解决方案就是 -

def n_largest_setarr(a, n=2):
    # a : Input array
    # n : We want n-max element position to be set to 1
    out = np.zeros_like(a)
    out[np.arange(len(a)), np.argpartition(a,-n, axis=1)[:,-n]] = 1
    return out

示例运行 -

# Input array
In [68]: a
Out[68]: 
array([[222, 460, 240, 846, 997, 923, 327, 492],
       [135, 178, 882, 345, 827, 402, 837, 812],
       [820, 838, 666, 143, 122, 727, 323, 249]])

# Use proposed method for various `n` values
In [69]: n_largest_setarr(a, n=2) # second max position set to 1
Out[69]: 
array([[0, 0, 0, 0, 0, 1, 0, 0],
       [0, 0, 0, 0, 0, 0, 1, 0],
       [1, 0, 0, 0, 0, 0, 0, 0]])

In [70]: n_largest_setarr(a, n=3) # third max position set to 1
Out[70]: 
array([[0, 0, 0, 1, 0, 0, 0, 0],
       [0, 0, 0, 0, 1, 0, 0, 0],
       [0, 0, 0, 0, 0, 1, 0, 0]])

# Use the sorted array to verify values
In [71]: np.sort(a,axis=1)
Out[71]: 
array([[222, 240, 327, 460, 492, 846, 923, 997],
       [135, 178, 345, 402, 812, 827, 837, 882],
       [122, 143, 249, 323, 666, 727, 820, 838]])