使用numpy操作,从每行填充的numpy数组(不包括pad)和非填充值中选择随机数的最快方法

2024-10-03 00:31:04 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个2D numpy数组,每一行都被填充(下面的例子中为-1)

对于每一行,我想选择一个随机数,不包括填充,并且只使用numpy操作获取每一行的非填充值的数量

这里是一个最小的例子。我为pad选择了-1,但是pad可以通过任何负int

import numpy as np
numList = [[0, 32, 84, 93, 1023, -1], [0, 23, 33, 45, -1, -1], [0, 10, 15, 21, 24, 25], [0, 23, -1, -1, -1, -1], [0 , 13, 33, 34, -1, -1]]
numArray = np.array(numList)
numArray

array([[   0,   32,   84,   93, 1023,   -1],
       [   0,   23,   33,   45,   -1,   -1],
       [   0,   10,   15,   21,   24,   25],
       [   0,   23,   -1,   -1,   -1,   -1],
       [   0,   13,   33,   34,   -1,   -1]])

对于长度,输出应该如下所示

LengthsResults
[5, 4, 6, 2, 4]. 

下面是一个示例输出,用于为每行拾取一个随机的非焊盘编号

randomNonPad
[84, 45, 0, 0, 34]

编辑:

我在看np.where,它可以让你在条件下过滤出numpy数组的一部分,还有numpy随机选择,它可以让你为数组选择一个随机数。我不确定如何处理np。尽管如此,似乎您可以将其更改为某些内容,但我还不确定是什么,甚至不确定它是否是正确的方法。对于python,您可以从列表开始,并将其附加到任意长度,但是对于numpy,您需要提前建立数组长度


Tags: importnumpy示例数量asnp数组array
2条回答

行中负数的索引也是非填充元素的长度,最简单的方法是

lengths = np.argmin(numArray, axis=1)

这假定行中所有元素的填充编号都相同。对于没有负数的行,这将无法正常工作,因此您可以使用以下方法进行修复:

lengths[np.take_along_axis(numArray, lengths.reshape(-1, 1), axis=1).ravel() >= 0] = numArray.shape[1]

现在,您可以使用此信息在行中生成随机索引数组:

indices = np.random.randint(lengths)

并应用索引以获得相应的元素:

result = np.take_along_axis(numArray, indices.reshape(-1, 1), axis=1)

虽然清理lengths数组可能是更快的选择,但较短的表达式可能类似于

lengths = np.where(np.any(numArray < 0, axis=1), np.argmin(numArray, axis=1), numArray.shape[1])

此外,如果填充数字不是一致的负数,则需要将np.argmin(numArray, axis=1)替换为np.argmax(numArray < 0, axis=1)np.argmin(numArray >= 0, axis=1),无论使用哪种方法计算lengths

注意-这可能与@Mad的答案重叠;我会留下它,以防另一种解释澄清了一些困惑

In [32]: numList = [[0, 32, 84, 93, 1023, -1], [0, 23, 33, 45, -1, -1], [0, 10, 15, 21, 2
    ...: 4, 25], [0, 23, -1, -1, -1, -1], [0 , 13, 33, 34, -1, -1]] 
    ...: numArray = np.array(numList)                                                    
In [33]: numArray                                                                        
Out[33]: 
array([[   0,   32,   84,   93, 1023,   -1],
       [   0,   23,   33,   45,   -1,   -1],
       [   0,   10,   15,   21,   24,   25],
       [   0,   23,   -1,   -1,   -1,   -1],
       [   0,   13,   33,   34,   -1,   -1]])

每行的焊盘数量:

In [34]: np.sum(numArray==-1, axis=1)                                                    
Out[34]: array([1, 2, 0, 4, 2])

每行非焊盘的数量:

In [35]: np.sum(numArray!=-1, axis=1)                                                    
Out[35]: array([5, 4, 6, 2, 4])

我不知道假设pad值都在末尾,这是否会提高效率。样本有点小,不能很好地进行计时

从每一行中随机选取一个非pad,显然第一次尝试是一个行列表:

In [40]: [np.random.choice(row[row!=-1]) for row in numArray]                            
Out[40]: [32, 0, 0, 23, 34]

或者根据长度(如上所述)(并假设尾部填充),我们可以为每行选择一个随机索引:

In [46]: [np.random.choice(i) for i in Out[35]]                                          
Out[46]: [1, 2, 1, 0, 1]
In [47]: numArray[np.arange(numArray.shape[0]), [np.random.choice(i) for i in Out[35]]]  
Out[47]: array([93, 45, 21, 23, 13])

在@Mad的帽子提示中,randint接受范围值的列表/数组,choice理解可以替换为:

In [49]: np.random.randint(Out[35])                                                      
Out[49]: array([3, 1, 2, 1, 1])
In [50]: numArray[np.arange(numArray.shape[0]), np.random.randint(Out[35])]              
Out[50]: array([ 0, 23, 24,  0,  0])

相关问题 更多 >