访问数组的多个元素
Access multiple elements of an array
有没有办法在一次操作中获取这些元素的已知行和列的数组元素?在每一行中,我想访问从 col_start 到 col_end 的元素(每行都有不同的起始和结束索引)。每行的元素数量相同,元素是连续的。
示例:
[ . . . . | | | . . . . . ]
[ | | | . . . . . . . . . ]
[ . . | | | . . . . . . . ]
[ . . . . . . . . | | | . ]
一种解决方案是获取元素的索引(行-列对),然后使用 my_array[row_list,col_list]。
有没有不使用for循环的其他(更简单)方法?
我想您正在寻找类似下面的内容。不过,我不确定您访问它们时想对它们做什么。
indexes = [(4,6), (0,2), (2,4), (8, 10)]
arr = [
[ . . . . | | | . . . . . ],
[ | | | . . . . . . . . . ],
[ . . | | | . . . . . . . ],
[ . . . . . . . . | | | . ]
]
for x in zip(indexes, arr):
index = x[0]
row = x[1]
print row[index[0]:index[1]+1]
A = np.arange(40).reshape(4,10)*.1
startend = [[2,5],[3,6],[4,7],[5,8]]
index_list = [np.arange(v[0],v[1]) + i*A.shape[1]
for i,v in enumerate(startend)]
# [array([2, 3, 4]), array([13, 14, 15]), array([24, 25, 26]), array([35, 36, 37])]
A.flat[index_list]
生产
array([[ 0.2, 0.3, 0.4],
[ 1.3, 1.4, 1.5],
[ 2.4, 2.5, 2.6],
[ 3.5, 3.6, 3.7]])
这仍然有一个迭代,但它是列表上的一个相当基本的迭代。
我正在索引 A
的扁平化 1d 版本。 np.take(A, index_list)
也有效。
如果行间隔的大小不同,我可以使用 np.r_
来连接它们。这不是绝对必要的,但在从多个区间和值构建索引时它很方便。
A.flat[np.r_[tuple(index_list)]]
# array([ 0.2, 0.3, 0.4, 1.3, 1.4, 1.5, 2.4, 2.5, 2.6, 3.5, 3.6, 3.7])
ajcr
使用的idx
可以不用choose
:
idx = [np.arange(v[0], v[1]) for i,v in enumerate(startend)]
A[np.arange(A.shape[0])[:,None], idx]
idx
就像我的 index_list
只是它不添加行长度。
np.array(idx)
array([[2, 3, 4],
[3, 4, 5],
[4, 5, 6],
[5, 6, 7]])
由于每个arange
的长度相同,所以可以不用迭代生成idx
:
col_start = np.array([2,3,4,5])
idx = col_start[:,None] + np.arange(3)
第一个索引是一个列数组,广播以匹配此idx
。
np.arange(A.shape[0])[:,None]
array([[0],
[1],
[2],
[3]])
有了这个 A
和 idx
我得到以下时间:
In [515]: timeit np.choose(idx,A.T[:,:,None])
10000 loops, best of 3: 30.8 µs per loop
In [516]: timeit A[np.arange(A.shape[0])[:,None],idx]
100000 loops, best of 3: 10.8 µs per loop
In [517]: timeit A.flat[idx+np.arange(A.shape[0])[:,None]*A.shape[1]]
10000 loops, best of 3: 24.9 µs per loop
flat
索引速度更快,但计算更高级的索引需要一些时间。
对于大型数组,flat
索引的速度占主导地位。
A=np.arange(4000).reshape(40,100)*.1
col_start=np.arange(20,60)
idx=col_start[:,None]+np.arange(30)
In [536]: timeit A[np.arange(A.shape[0])[:,None],idx]
10000 loops, best of 3: 108 µs per loop
In [537]: timeit A.flat[idx+np.arange(A.shape[0])[:,None]*A.shape[1]]
10000 loops, best of 3: 59.4 µs per loop
np.choose
方法遇到硬编码限制:Need between 2 and (32) array objects (inclusive).
什么越界idx
?
col_start=np.array([2,4,6,8])
idx=col_start[:,None]+np.arange(3)
A[np.arange(A.shape[0])[:,None], idx]
产生错误,因为最后一个 idx
值是 10
,太大。
你可以clip
idx
idx=idx.clip(0,A.shape[1]-1)
在最后一行产生重复值
[ 3.8, 3.9, 3.9]
您也可以在索引前填充 A
。有关更多选项,请参阅 np.pad
。
np.pad(A,((0,0),(0,2)),'edge')[np.arange(A.shape[0])[:,None], idx]
另一种选择是删除越界值。 idx
将变成参差不齐的列表列表(或列表数组)。 flat
方法可以解决这个问题,但结果不会是矩阵。
startend = [[2,5],[4,7],[6,9],[8,10]]
index_list = [np.arange(v[0],v[1]) + i*A.shape[1]
for i,v in enumerate(startend)]
# [array([2, 3, 4]), array([14, 15, 16]), array([26, 27, 28]), array([38, 39])]
A.flat[np.r_[tuple(index_list)]]
# array([ 0.2, 0.3, 0.4, 1.4, 1.5, 1.6, 2.6, 2.7, 2.8, 3.8, 3.9])
您可以使用 np.choose
.
这是一个 NumPy 数组示例 arr
:
array([[ 0, 1, 2, 3, 4, 5, 6],
[ 7, 8, 9, 10, 11, 12, 13],
[14, 15, 16, 17, 18, 19, 20]])
假设我们要从第一行选择值 [1, 2, 3]
,从第二行选择值 [11, 12, 13]
,从第三行选择值 [17, 18, 19]
。
换句话说,我们将从 arr
的每一行中挑选出索引,如数组 idx
:
所示
array([[1, 2, 3],
[4, 5, 6],
[3, 4, 5]])
然后使用 np.choose
:
>>> np.choose(idx, arr.T[:,:,np.newaxis])
array([[ 1, 2, 3],
[11, 12, 13],
[17, 18, 19]])
解释刚刚发生的事情:arr.T[:,:,np.newaxis]
意味着 arr
暂时被视为具有形状 (7, 3, 1)
的 3D 数组。您可以将其想象成 3D 数组,其中原始 arr
的每一列现在都是具有三个值的二维列向量。 3D 数组看起来有点像这样:
# 0 1 2 3 4 5 6
[[ 0] [[ 1] [[ 2] [[ 3] [[ 4] [[ 5] [[ 6] # choose values from 1, 2, 3
[ 7] [ 8] [ 9] [10] [11] [12] [13] # choose values from 4, 5, 6
[14]] [15]] [16]] [17]] [18]] [19]] [20]] # choose values from 3, 4, 5
要获取输出数组的第 zeroth 行,choose
从索引处的二维列中选择 zeroth 元素1
,索引 2
处二维列中的 zeroth 元素,索引 2
处二维列中的 zeroth 元素指数 3
。
要获取输出数组的 first 行,choose
从索引处的二维列中选择 first 元素4
,索引 5
处二维列的 第一个 元素,...等等。
有没有办法在一次操作中获取这些元素的已知行和列的数组元素?在每一行中,我想访问从 col_start 到 col_end 的元素(每行都有不同的起始和结束索引)。每行的元素数量相同,元素是连续的。 示例:
[ . . . . | | | . . . . . ]
[ | | | . . . . . . . . . ]
[ . . | | | . . . . . . . ]
[ . . . . . . . . | | | . ]
一种解决方案是获取元素的索引(行-列对),然后使用 my_array[row_list,col_list]。
有没有不使用for循环的其他(更简单)方法?
我想您正在寻找类似下面的内容。不过,我不确定您访问它们时想对它们做什么。
indexes = [(4,6), (0,2), (2,4), (8, 10)]
arr = [
[ . . . . | | | . . . . . ],
[ | | | . . . . . . . . . ],
[ . . | | | . . . . . . . ],
[ . . . . . . . . | | | . ]
]
for x in zip(indexes, arr):
index = x[0]
row = x[1]
print row[index[0]:index[1]+1]
A = np.arange(40).reshape(4,10)*.1
startend = [[2,5],[3,6],[4,7],[5,8]]
index_list = [np.arange(v[0],v[1]) + i*A.shape[1]
for i,v in enumerate(startend)]
# [array([2, 3, 4]), array([13, 14, 15]), array([24, 25, 26]), array([35, 36, 37])]
A.flat[index_list]
生产
array([[ 0.2, 0.3, 0.4],
[ 1.3, 1.4, 1.5],
[ 2.4, 2.5, 2.6],
[ 3.5, 3.6, 3.7]])
这仍然有一个迭代,但它是列表上的一个相当基本的迭代。
我正在索引 A
的扁平化 1d 版本。 np.take(A, index_list)
也有效。
如果行间隔的大小不同,我可以使用 np.r_
来连接它们。这不是绝对必要的,但在从多个区间和值构建索引时它很方便。
A.flat[np.r_[tuple(index_list)]]
# array([ 0.2, 0.3, 0.4, 1.3, 1.4, 1.5, 2.4, 2.5, 2.6, 3.5, 3.6, 3.7])
ajcr
使用的idx
可以不用choose
:
idx = [np.arange(v[0], v[1]) for i,v in enumerate(startend)]
A[np.arange(A.shape[0])[:,None], idx]
idx
就像我的 index_list
只是它不添加行长度。
np.array(idx)
array([[2, 3, 4],
[3, 4, 5],
[4, 5, 6],
[5, 6, 7]])
由于每个arange
的长度相同,所以可以不用迭代生成idx
:
col_start = np.array([2,3,4,5])
idx = col_start[:,None] + np.arange(3)
第一个索引是一个列数组,广播以匹配此idx
。
np.arange(A.shape[0])[:,None]
array([[0],
[1],
[2],
[3]])
有了这个 A
和 idx
我得到以下时间:
In [515]: timeit np.choose(idx,A.T[:,:,None])
10000 loops, best of 3: 30.8 µs per loop
In [516]: timeit A[np.arange(A.shape[0])[:,None],idx]
100000 loops, best of 3: 10.8 µs per loop
In [517]: timeit A.flat[idx+np.arange(A.shape[0])[:,None]*A.shape[1]]
10000 loops, best of 3: 24.9 µs per loop
flat
索引速度更快,但计算更高级的索引需要一些时间。
对于大型数组,flat
索引的速度占主导地位。
A=np.arange(4000).reshape(40,100)*.1
col_start=np.arange(20,60)
idx=col_start[:,None]+np.arange(30)
In [536]: timeit A[np.arange(A.shape[0])[:,None],idx]
10000 loops, best of 3: 108 µs per loop
In [537]: timeit A.flat[idx+np.arange(A.shape[0])[:,None]*A.shape[1]]
10000 loops, best of 3: 59.4 µs per loop
np.choose
方法遇到硬编码限制:Need between 2 and (32) array objects (inclusive).
什么越界idx
?
col_start=np.array([2,4,6,8])
idx=col_start[:,None]+np.arange(3)
A[np.arange(A.shape[0])[:,None], idx]
产生错误,因为最后一个 idx
值是 10
,太大。
你可以clip
idx
idx=idx.clip(0,A.shape[1]-1)
在最后一行产生重复值
[ 3.8, 3.9, 3.9]
您也可以在索引前填充 A
。有关更多选项,请参阅 np.pad
。
np.pad(A,((0,0),(0,2)),'edge')[np.arange(A.shape[0])[:,None], idx]
另一种选择是删除越界值。 idx
将变成参差不齐的列表列表(或列表数组)。 flat
方法可以解决这个问题,但结果不会是矩阵。
startend = [[2,5],[4,7],[6,9],[8,10]]
index_list = [np.arange(v[0],v[1]) + i*A.shape[1]
for i,v in enumerate(startend)]
# [array([2, 3, 4]), array([14, 15, 16]), array([26, 27, 28]), array([38, 39])]
A.flat[np.r_[tuple(index_list)]]
# array([ 0.2, 0.3, 0.4, 1.4, 1.5, 1.6, 2.6, 2.7, 2.8, 3.8, 3.9])
您可以使用 np.choose
.
这是一个 NumPy 数组示例 arr
:
array([[ 0, 1, 2, 3, 4, 5, 6],
[ 7, 8, 9, 10, 11, 12, 13],
[14, 15, 16, 17, 18, 19, 20]])
假设我们要从第一行选择值 [1, 2, 3]
,从第二行选择值 [11, 12, 13]
,从第三行选择值 [17, 18, 19]
。
换句话说,我们将从 arr
的每一行中挑选出索引,如数组 idx
:
array([[1, 2, 3],
[4, 5, 6],
[3, 4, 5]])
然后使用 np.choose
:
>>> np.choose(idx, arr.T[:,:,np.newaxis])
array([[ 1, 2, 3],
[11, 12, 13],
[17, 18, 19]])
解释刚刚发生的事情:arr.T[:,:,np.newaxis]
意味着 arr
暂时被视为具有形状 (7, 3, 1)
的 3D 数组。您可以将其想象成 3D 数组,其中原始 arr
的每一列现在都是具有三个值的二维列向量。 3D 数组看起来有点像这样:
# 0 1 2 3 4 5 6
[[ 0] [[ 1] [[ 2] [[ 3] [[ 4] [[ 5] [[ 6] # choose values from 1, 2, 3
[ 7] [ 8] [ 9] [10] [11] [12] [13] # choose values from 4, 5, 6
[14]] [15]] [16]] [17]] [18]] [19]] [20]] # choose values from 3, 4, 5
要获取输出数组的第 zeroth 行,choose
从索引处的二维列中选择 zeroth 元素1
,索引 2
处二维列中的 zeroth 元素,索引 2
处二维列中的 zeroth 元素指数 3
。
要获取输出数组的 first 行,choose
从索引处的二维列中选择 first 元素4
,索引 5
处二维列的 第一个 元素,...等等。