访问不在给定索引列表中的 NumPy 数组元素
Accessing NumPy array elements not in a given index list
我有一个形状为 (100, 170, 256) 的 NumPy 数组。我有一个由索引 [0, 10, 20, 40, 70].
组成的数组
我可以得到索引对应的子数组如下:
sub_array = array[..., index]
这 returns 一个具有预期形状 (100, 170, 5) 的数组。现在,我正在尝试取补码并获得与这些索引不对应的子数组。所以,我做了:
sub_array = array[..., ~index]
出于某种原因,这仍然是 returns 我的形状数组 (100, 170, 5)。我想知道如何在python中对这些索引进行补码操作?
[编辑]
也尝试过:
sub_array = array[..., not(index.any)]
但是,这也不能满足我的要求(获取形状数组 (100, 170, 251))。
为了避免这个问题,我倾向于使用布尔数组而不是索引。您可以使用 in1d
获得一个,即使它不是很漂亮:
>>> arr[..., index].shape
(100, 170, 5)
>>> arr[..., np.in1d(np.arange(arr.shape[-1]),index)].shape
(100, 170, 5)
>>> arr[..., ~np.in1d(np.arange(arr.shape[-1]),index)].shape
(100, 170, 251)
看看 ~index 给你的是什么 - 我认为是:
array([ -1, -11, -21, -41, -71])
所以,你的电话
sub_array = array[..., ~index]
将 return 5 个条目,对应于索引 [-1、-11、-21、-41、-71],即在您的情况下为 255、245、235、215 和 185
同样,not(index.any) 给出
False
这就是为什么你的第二次尝试不起作用
这应该有效:
sub_array = array[..., [i for i in xrange(256) if i not in index]]
我假设 index
是一个 numpy 数组 - 如果是这样,可以在此处找到波浪符操作符的解释:
What does the unary operator ~ do in numpy?
至于你想要完成的事情,你可以assemble一个互补的索引数组:
notIndex = numpy.array([i for i in xrange(256) if i not in index])
然后使用notIndex
代替index
。
您获取数据的方式,最简单的方法是使用 np.delete
:
sub_array = np.delete(array, index, axis=2)
或者,您尝试使用的逻辑运算符可以按照@DSM 的建议应用于布尔数组:
mask = np.ones(a.shape[2], dtype=bool)
mask[index] = False
sub_array = array[:,:, mask]
(我不会调用你的数组 array
但我遵循了你问题中的名称)
问题已回答,但我在这里提出三种方法的基准。
最快的解决方案是布尔掩码(具有较小和较大的索引数组大小)
mask = np.ones(arr.size, dtype=bool)
mask[indexes] = False
result = arr[mask]
它比列表理解快 2000 倍,比 np.delete
快一点
重现代码
三个建议的解决方案:列表理解(sol1
)、布尔掩码(sol2
)或np.delete
(sol3
)
d = 100000
a = np.random.rand(d)
idx = np.random.randint(d, size = 10)
# list comprehension
def sol1(arr, indexes):
return arr[[i for i in range(arr.size) if i not in indexes]]
sol1(a, idx)
# Out[30]: array([0.13044518, 0.68564961, 0.03033223, ..., 0.03796257, 0.40137137, 0.45403929])
# boolean mask
def sol2(arr, indexes):
mask = np.ones(arr.size, dtype=bool)
mask[indexes] = False
return arr[mask]
sol2(a, idx)
# Out[32]: array([0.13044518, 0.68564961, 0.03033223, ..., 0.03796257, 0.40137137, 0.45403929])
# np.delete
def sol3(arr, indexes):
return np.delete(arr, indexes)
sol3(a, idx)
# Out[36]: array([0.13044518, 0.68564961, 0.03033223, ..., 0.03796257, 0.40137137, 0.45403929])
结果
%timeit sol1(a, idx)
384 ms ± 2.75 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit sol2(a, idx)
154 µs ± 15.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit sol3(a, idx)
194 µs ± 18.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
idx = np.random.randint(d, size = 1000)
%timeit sol1(a, idx)
386 ms ± 7.75 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit sol2(a, idx)
171 µs ± 11.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit sol3(a, idx)
205 µs ± 10.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
我有一个形状为 (100, 170, 256) 的 NumPy 数组。我有一个由索引 [0, 10, 20, 40, 70].
组成的数组我可以得到索引对应的子数组如下:
sub_array = array[..., index]
这 returns 一个具有预期形状 (100, 170, 5) 的数组。现在,我正在尝试取补码并获得与这些索引不对应的子数组。所以,我做了:
sub_array = array[..., ~index]
出于某种原因,这仍然是 returns 我的形状数组 (100, 170, 5)。我想知道如何在python中对这些索引进行补码操作?
[编辑]
也尝试过:
sub_array = array[..., not(index.any)]
但是,这也不能满足我的要求(获取形状数组 (100, 170, 251))。
为了避免这个问题,我倾向于使用布尔数组而不是索引。您可以使用 in1d
获得一个,即使它不是很漂亮:
>>> arr[..., index].shape
(100, 170, 5)
>>> arr[..., np.in1d(np.arange(arr.shape[-1]),index)].shape
(100, 170, 5)
>>> arr[..., ~np.in1d(np.arange(arr.shape[-1]),index)].shape
(100, 170, 251)
看看 ~index 给你的是什么 - 我认为是:
array([ -1, -11, -21, -41, -71])
所以,你的电话
sub_array = array[..., ~index]
将 return 5 个条目,对应于索引 [-1、-11、-21、-41、-71],即在您的情况下为 255、245、235、215 和 185
同样,not(index.any) 给出
False
这就是为什么你的第二次尝试不起作用
这应该有效:
sub_array = array[..., [i for i in xrange(256) if i not in index]]
我假设 index
是一个 numpy 数组 - 如果是这样,可以在此处找到波浪符操作符的解释:
What does the unary operator ~ do in numpy?
至于你想要完成的事情,你可以assemble一个互补的索引数组:
notIndex = numpy.array([i for i in xrange(256) if i not in index])
然后使用notIndex
代替index
。
您获取数据的方式,最简单的方法是使用 np.delete
:
sub_array = np.delete(array, index, axis=2)
或者,您尝试使用的逻辑运算符可以按照@DSM 的建议应用于布尔数组:
mask = np.ones(a.shape[2], dtype=bool)
mask[index] = False
sub_array = array[:,:, mask]
(我不会调用你的数组 array
但我遵循了你问题中的名称)
问题已回答,但我在这里提出三种方法的基准。
最快的解决方案是布尔掩码(具有较小和较大的索引数组大小)
mask = np.ones(arr.size, dtype=bool)
mask[indexes] = False
result = arr[mask]
它比列表理解快 2000 倍,比 np.delete
重现代码
三个建议的解决方案:列表理解(sol1
)、布尔掩码(sol2
)或np.delete
(sol3
)
d = 100000
a = np.random.rand(d)
idx = np.random.randint(d, size = 10)
# list comprehension
def sol1(arr, indexes):
return arr[[i for i in range(arr.size) if i not in indexes]]
sol1(a, idx)
# Out[30]: array([0.13044518, 0.68564961, 0.03033223, ..., 0.03796257, 0.40137137, 0.45403929])
# boolean mask
def sol2(arr, indexes):
mask = np.ones(arr.size, dtype=bool)
mask[indexes] = False
return arr[mask]
sol2(a, idx)
# Out[32]: array([0.13044518, 0.68564961, 0.03033223, ..., 0.03796257, 0.40137137, 0.45403929])
# np.delete
def sol3(arr, indexes):
return np.delete(arr, indexes)
sol3(a, idx)
# Out[36]: array([0.13044518, 0.68564961, 0.03033223, ..., 0.03796257, 0.40137137, 0.45403929])
结果
%timeit sol1(a, idx)
384 ms ± 2.75 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit sol2(a, idx)
154 µs ± 15.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit sol3(a, idx)
194 µs ± 18.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
idx = np.random.randint(d, size = 1000)
%timeit sol1(a, idx)
386 ms ± 7.75 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit sol2(a, idx)
171 µs ± 11.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit sol3(a, idx)
205 µs ± 10.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)