为了账号安全,请及时绑定邮箱和手机立即绑定

使用 numpy 操作从每行填充的 numpy 数组和非填充值的数量中选择随机数的最快方法

使用 numpy 操作从每行填充的 numpy 数组和非填充值的数量中选择随机数的最快方法

莫回无 2022-12-06 15:05:49
我有一个 2D numpy 数组,每一行都填充了(下面的示例使用 -1)。对于每一行,我想选择一个随机数,不包括填充,并仅使用 numpy 操作获取每一行的非填充值的数量。这是一个最小的例子。我为 pad 选择了 -1,但 pad 可以是任何负整数。import numpy as npnumList = [[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)numArrayarray([[   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.where,但似乎您可以将其更改为某些东西,但我不确定是什么,或者即使它是正确的方法。对于 python,您可以从一个列表开始,并将其附加到任意长度,但对于 numpy,您需要提前建立数组长度。
查看完整描述

2 回答

?
烙印99

TA贡献1829条经验 获得超13个赞

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

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


查看完整回答
反对 回复 2022-12-06
?
慕田峪9158850

TA贡献1794条经验 获得超7个赞

注意——这可能与@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])

我不知道假设填充值都在最后是否会使它更有效率。样本有点小,无法把握好时机。


从每一行中随机选择一个非填充,显而易见的第一次尝试是行列表理解:


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])


查看完整回答
反对 回复 2022-12-06
  • 2 回答
  • 0 关注
  • 92 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信