使用 Pythonic 矢量化代码在 2D numpy 数组中索引不同大小的范围
Indexing different sized ranges in a 2D numpy array using a Pythonic vectorized code
我有一个 numpy 二维数组,我想 select 这个数组的不同大小范围,具体取决于列索引。这是输入数组 a = np.reshape(np.array(range(15)), (5, 3))
示例
[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]
[ 9 10 11]
[12 13 14]]
然后,列表b = [4,3,1]
确定每个列切片的不同范围大小,这样我们就可以得到数组
[0 3 6 9]
[1 4 7]
[2]
我们可以将其连接并展平以获得最终所需的输出
[0 3 6 9 1 4 7 2]
目前,要执行此任务,我正在使用以下代码
slices = []
for i in range(a.shape[1]):
slices.append(a[:b[i],i])
c = np.concatenate(slices)
并且,如果可能的话,我想将其转换为 pythonic 格式。
奖励: 同样的问题,但现在考虑 b
确定行切片而不是列。
我们可以使用 broadcasting
生成合适的掩码,然后 masking
完成工作 -
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])
我有一个 numpy 二维数组,我想 select 这个数组的不同大小范围,具体取决于列索引。这是输入数组 a = np.reshape(np.array(range(15)), (5, 3))
示例
[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]
[ 9 10 11]
[12 13 14]]
然后,列表b = [4,3,1]
确定每个列切片的不同范围大小,这样我们就可以得到数组
[0 3 6 9]
[1 4 7]
[2]
我们可以将其连接并展平以获得最终所需的输出
[0 3 6 9 1 4 7 2]
目前,要执行此任务,我正在使用以下代码
slices = []
for i in range(a.shape[1]):
slices.append(a[:b[i],i])
c = np.concatenate(slices)
并且,如果可能的话,我想将其转换为 pythonic 格式。
奖励: 同样的问题,但现在考虑 b
确定行切片而不是列。
我们可以使用 broadcasting
生成合适的掩码,然后 masking
完成工作 -
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])