Numpy 索引:返回其余部分

Posted

技术标签:

【中文标题】Numpy 索引:返回其余部分【英文标题】:Numpy Indexing: Return the rest 【发布时间】:2012-09-13 03:20:27 【问题描述】:

一个简单的numpy索引示例:

In: a = numpy.arange(10)
In: sel_id = numpy.arange(5)
In: a[sel_id]
Out: array([0,1,2,3,4])

如何返回未被 sel_id 索引的数组的其余部分?我能想到的是:

In: numpy.array([x for x in a if x not in a[id]])
out: array([5,6,7,8,9])

有没有更简单的方法?

【问题讨论】:

这是一次操作吗?或者你会在路上重复使用sel_id(这是否定的)?另外,您是对多维案例感兴趣,还是只对一维案例感兴趣? 在我的应用中,会在多维海量数组上操作,是的,我会复用sel_id。 刚刚意识到我上面的解决方案是错误的。如果它是一个包含十个 1 的数组,那么给定的代码将给出一个 None 数组,而不是一个包含五个 1 的数组。 【参考方案1】:

对于这个简单的一维案例,我实际上会使用布尔掩码:

a = numpy.arange(10)
include_index = numpy.arange(4)
include_idx = set(include_index)  #Set is more efficient, but doesn't reorder your elements if that is desireable
mask = numpy.array([(i in include_idx) for i in xrange(len(a))])

现在你可以得到你的价值观了:

included = a[mask]  # array([0, 1, 2, 3])
excluded = a[~mask] # array([4, 5, 6, 7, 8, 9])

请注意,a[mask] 不一定产生与a[include_index] 相同的结果,因为include_index 的顺序对那种情况下的输出很重要(它应该大致相当于a[sorted(include_index)])。但是,由于您排除项目的顺序没有明确定义,这应该可以正常工作。


编辑

创建蒙版的更好方法是:

mask = np.zeros(a.shape,dtype=bool)
mask[include_idx] = True

(感谢 seberg)

【讨论】:

@BiRico -- 错误。我将include_index 转换为set(称为include_idx),它有一个在O(1) 中的__contains__ 方法。此解决方案具有O(N) 复杂性。 +1,这几乎正是我要建议的,但我不得不离开电脑。使用布尔掩码非常适合此类操作,因为您不必做任何额外的工作来计算相对补码。仅供参考,根据我的测试,在生成器上使用 fromiter 而不是在列表理解上使用 array 会产生小的速度提升。 抱歉,使用套装来制作面具是为了一个小问题而拿出大型武器...... 可能是另一种创建布尔数组的方式可以是:mask = numpy.zeros(numpy.shape(a),bool);掩码 [sel_id] = 真;我同意使用布尔数组可能是最好的解决方案。谢谢! @mgilson,如果您不想罚款,但是您如何编辑答案以使用mask[sel_id] = True。这将使它成为某人找到的非常好的答案。 (是的,我真的认为布景在这里很糟糕,原因有很多)【参考方案2】:

你可以用布尔掩码很好地做到这一点:

a = numpy.arange(10)

mask = np.ones(len(a), dtype=bool) # all elements included/True.
mask[[7,2,8]] = False              # Set unwanted elements to False

print a[mask]
# Gives (removing entries 7, 2 and 8):
[0 1 3 4 5 6 9]

加法(取自@mgilson)。创建的二进制掩码可以很好地用于返回带有a[~mask] 的原始切片,但只有在原始索引经过排序时才相同。


编辑: 下移了,因为我必须意识到此时(2012 年 9 月)我会考虑 np.delete 错误。

您也可以使用np.delete,尽管掩码功能更强大(并且在未来我认为这应该是一个不错的选择)。但是目前它比上面的要慢,并且会产生带有负索引的意外结果(或给定切片时的步骤)。

print np.delete(a, [7,2,8])

【讨论】:

是的——第二种方法是迄今为止最好的,唯一的纯 numpy 线性方法……回想起来似乎很明显! (请注意,在幕后,numpy.delete 只使用setdiff1d,而in1d 又使用in1d。所以它也是n log n。)+1 但你已经有了我的! @senderle 认真的!这很有趣,也许np.delete 可以使用该执行路径的更改... @PierreGM,真的,我也从不使用它,但如果你只想要一个没有它的数组副本而不需要其他任何东西,老实说,我认为使用这样的函数没有什么大问题。 @seberg 它存在的事实意味着np.delete 当然对某些人有用,但我一直认为这是一个糟糕的功能,永远不会像人们期望的那样工作(但工作方式与这应该)。当显式的精美索引如此清晰时,为什么还要增加混乱?【参考方案3】:

更像是:

a = numpy.array([1, 2, 3, 4, 5, 6, 7, 4])
exclude_index = numpy.arange(5)
include_index = numpy.setdiff1d(numpy.arange(len(a)), exclude_index)
a[include_index]
# array([6, 7, 4])

# Notice this is a little different from
numpy.setdiff1d(a, a[exclude_index])
# array([6, 7]

【讨论】:

【参考方案4】:

我会用布尔掩码来做这件事,但有点不同。这具有在 N 维中工作的好处,具有连续或非索引。内存使用情况取决于是否为掩码数组创建视图或副本,我不确定。

import numpy
a = numpy.arange(10)
sel_id = numpy.arange(5)
mask = numpy.ma.make_mask_none(a.shape)
mask[sel_id] = True
answer = numpy.ma.masked_array(a, mask).compressed()
print answer
# [5 6 7 8 9]

【讨论】:

掩码数组可能是一个非常好的选择。虽然.compressed() 在某种程度上违背了 IMO 屏蔽数组的目的,因为它创建了一个普通的数组副本。【参考方案5】:

此外,如果它们是连续的,请使用 [N:] 语法来选择其余部分。例如, arr[5:] 将选择数组中倒数第 5 个元素。

【讨论】:

【参考方案6】:

这是另一种方式,使用 numpy 的 isin() 函数:

import numpy as np

a = np.arange(10)
sel_id = np.arange(5)

a[~np.isin(np.arange(a.size), sel_id)]

解释:

np.arange(a.size) 给出a 的所有索引,即[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

np.isin(np.arange(a.size), sel_id)sel_idFalse 中的索引处返回布尔掩码[ True, True, True, True, True, False, False, False, False, False]True。由于我们想要获取不在sel_id 中的索引,我们使用按位非运算符~ 来反转布尔掩码。

【讨论】:

【参考方案7】:

numpy.setdiff1d(a, a[sel_id]) 应该可以解决问题。不知道有没有比这更简洁的东西。

【讨论】:

如果数组中有重复的值,那就不行了。【参考方案8】:

假设a 是一维数组,您可以从索引列表中弹出您不想要的项目:

accept = [i for i in range(a.size) if i not in avoid_list]
a[accept]

你也可以尝试使用类似的东西

accept = sorted(set(range(a.size)) - set(indices_to_discard))
a[accept]

这个想法是在你不想要的索引集的互补上使用花哨的索引。

【讨论】:

以上是关于Numpy 索引:返回其余部分的主要内容,如果未能解决你的问题,请参考以下文章

numpy - 返回数组中元素的第一个索引[重复]

Python 关于数组矩阵变换函数numpy.nonzero(),numpy.multiply()用法

使用 numpy 从过滤后的排序数组返回索引

numpy的索引

python numpy maxpool:给定一个数组和来自argmax的索引,返回最大值

在 numpy 数组中搜索元素的索引