1个回答

6
我们可以使用“广播”来生成一个合适的掩码,然后“屏蔽”会完成这项工作。
In [150]: a
Out[150]: 
array([[ 0,  1,  2],
       [ 3,  4,  5],
       [ 6,  7,  8],
       [ 9, 10, 11],
       [12, 13, 14]])

In [151]: b
Out[151]: [4, 3, 1]

In [152]: mask = np.arange(len(a))[:,None] < b

In [153]: a.T[mask.T]
Out[153]: array([0, 3, 6, 9, 1, 4, 7, 2])

另一种掩盖的方法是 -

In [156]: a.T[np.greater.outer(b, np.arange(len(a)))]
Out[156]: array([0, 3, 6, 9, 1, 4, 7, 2])

奖金:按行切片

如果我们需要根据块大小按行进行切片,我们需要修改一些内容:

In [51]: a
Out[51]: 
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14]])

# slice lengths per row
In [52]: b
Out[52]: [4, 3, 1]

# Usual loop based solution :
In [53]: np.concatenate([a[i,:b_i] for i,b_i in enumerate(b)])
Out[53]: array([ 0,  1,  2,  3,  5,  6,  7, 10])

# Vectorized mask based solution :
In [54]: a[np.greater.outer(b, np.arange(a.shape[1]))]
Out[54]: array([ 0,  1,  2,  3,  5,  6,  7, 10])

这个解决方案非常聪明,非常感谢!此外,这非常有启发性,因为我不知道这个广播概念,而且它似乎非常有用。顺便说一句,我刚刚验证了第二种方法,外部方法使用了一个内部积,所以似乎会慢一些,对吗?对于大规模数据集,您认为速度差异会很显着吗? - xicocaio
@xicocaio 第二个避免了转置,但是转置不会复制。因此,最终我认为这两个应该是可比较的。 - Divakar
好的,但对于非常大的数组,两个向量的“外积”是不是很耗费计算资源? - xicocaio
[152] 也是一个“外部”比较。总的比较次数是相同的。不同之处更多是语法上的而不是实际的“工作”。 - hpaulj
@hpaulj 好的,我终于妥协了并研究了第一种方法,我想我明白你的意思了。你的想法是 < b 会隐式执行数组乘积和比较,对吗? - xicocaio
1
第一种方法:每个循环3.13微秒±20.9纳秒(7次运行的平均值±标准偏差,每个循环100,000次) 第二种方法:每个循环3.72微秒±421纳秒(7次运行的平均值±标准偏差,每个循环100,000次) 这不是最好的测试,因为我使用了5x3数组。但标准偏差表明第一种方法会更好地扩展。 - Prox

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接