【问题标题】:Finding indices of values in 2D numpy array在 2D numpy 数组中查找值的索引
【发布时间】:2025-12-18 18:55:02
【问题描述】:

我正在尝试从 numpy 数组中获取索引值,但我尝试使用 intersects 但无济于事。我只是想在 2 个数组中找到类似的值。一个是 2D,我正在选择一列,另一个是 1D,只是要搜索的值列表,因此实际上只有 2 个 1D 数组。

我们称这个数组为:

 array([[    1, 97553,     1],
       [    1, 97587,     1],
       [    1, 97612,     1],
       [    1, 97697,     1],
       [    1, 97826,     3],
       [    1, 97832,     1],
       [    1, 97839,     1],
       [    1, 97887,     1],
       [    1, 97944,     1],
       [    1, 97955,     2]])

我们正在搜索values = numpy.array([97612, 97633, 97697, 97999, 97943, 97944])

所以我试试:

numpy.where(a[:, 1] == values)

我希望有一堆值的索引,但我得到一个空数组,它吐出[(array([], dtype=int64),)]

如果我尝试这个:

numpy.where(a[:, 1] == 97697)

它给了我(array([2]),),这是我所期望的。

我在这里缺少什么奇怪的数组?或者是否有更简单的方法来做到这一点?查找数组索引和匹配数组似乎根本不像我预期的那样工作。当我想通过索引或唯一值查找数组的并集或相交时,它似乎不起作用。任何帮助都会很棒。谢谢。

编辑: 根据沃伦斯的要求:

import numpy

a = numpy.array([[    1, 97553,     1],
       [    1, 97587,     1],
       [    1, 97612,     1],
       [    1, 97697,     1],
       [    1, 97826,     3],
       [    1, 97832,     1],
       [    1, 97839,     1],
       [    1, 97887,     1],
       [    1, 97944,     1],
       [    1, 97955,     2]])

values = numpy.array([97612, 97633, 97697, 97999, 97943, 97944])

我发现numpy.in1d 会给我一个正确的布尔值真值表来进行操作,其中包含一个应该映射到原始数据的相同长度的一维数组。我现在唯一的问题是如何处理它,例如删除或修改这些索引处的原始数组。我可以用循环费力地做到这一点,但据我所知,numpy 有更好的方法。从我能找到的数据来看,作为掩码的真值表应该非常强大。

【问题讨论】:

  • “如果我尝试 numpy.intersect(a[:, 1], values),我应该会返回 97612、97697、97944。但我会得到一些毫无意义的东西。” 我假设你的意思是 @987654331 @;没有功能numpy.intersect。鉴于您在问题中显示的数据,np.intersect1d(a[:, 1], values) 返回array([97612, 97697, 97944])。显示完全你做了什么,并显示你得到的意想不到的结果。
  • @bobrobbob 可能值得注意的是,如果 B 中的值未包含在 A 中,则基于 np.searchsorted 的解决方案会给出错误且令人困惑的结果(它为您提供排序插入的索引) 所以这里需要进一步处理。
  • @bobrobbob OP 确实需要 BA 的子数组,这里不是这种情况
  • "...为了解决这个问题,我反复撕下它..." 呵呵,我知道那种感觉。 :) 我同意您可能向intersect1d 提供了“坏”数据。由于很明显 intersect1d 的行为不是问题的一部分,因此您可以从问题中删除有关它的 cmets。现在的方式只是混淆了问题。

标签: python arrays numpy


【解决方案1】:

np.where 与单个参数等效于 np.nonzero。它为您提供条件(输入数组)为True 的索引。

在您的示例中,您正在检查 a[:,1]values 之间的元素相等性

a[:, 1] == values
False

所以它给了你正确的结果:输入中没有索引是True

您应该改用 np.isin

np.isin(a[:,1], values)
array([False, False,  True,  True, False, False, False, False,  True, False], dtype=bool)

现在您可以使用 np.where 来获取索引

np.where(np.isin(a[:,1], values))
(array([2, 3, 8]),)

并使用它们来寻址原始数组

a[np.where(np.isin(a[:,1], values))]    
array([[    1, 97612,     1],
       [    1, 97697,     1],
       [    1, 97944,     1]])

您最初使用简单相等检查的解决方案确实可以使用正确的broadcasting

np.where(a[:,1] == values[..., np.newaxis])[1]
array([2, 3, 8])

编辑鉴于您似乎在使用上述结果来索引和操作您的数组时遇到问题,这里有几个简单的示例

现在您应该有两种方法可以访问原始数组中的匹配元素,二进制掩码或来自np.where 的索引。

mask = np.isin(a[:,1], values)  # np.in1d if np.isin is not available
idx = np.where(mask)

假设您要将所有匹配的行设置为零

a[mask] = 0   # or a[idx] = 0
array([[    1, 97553,     1],
       [    1, 97587,     1],
       [    0,     0,     0],
       [    0,     0,     0],
       [    1, 97826,     3],
       [    1, 97832,     1],
       [    1, 97839,     1],
       [    1, 97887,     1],
       [    0,     0,     0],
       [    1, 97955,     2]])

或者你想将匹配行的第三列乘以100

a[mask, 2] *= 100
array([[    1, 97553,     1],
       [    1, 97587,     1],
       [    1, 97612,   100],
       [    1, 97697,   100],
       [    1, 97826,     3],
       [    1, 97832,     1],
       [    1, 97839,     1],
       [    1, 97887,     1],
       [    1, 97944,   100],
       [    1, 97955,     2]])

或者你想删除匹配的行(这里使用索引比掩码更方便)

np.delete(a, idx, axis=0)
array([[    1, 97553,     1],
       [    1, 97587,     1],
       [    1, 97826,     3],
       [    1, 97832,     1],
       [    1, 97839,     1],
       [    1, 97887,     1],
       [    1, 97955,     2]])

【讨论】:

  • 'numpy.isin' 是我的第一个想法,但是它似乎在 python 2.7 中不存在,当我尝试使用它时,我收到错误消息,即模块中没有这样的属性麻木的。必须有某种方法来实现我正在尝试的目标。
  • @Will 哪个 NumPy 版本? np.isin 是在 1.13.0 中引入的,但您应该能够使用 np.in1d 获得相同的结果。实际上我在以前的答案版本中使用了np.in1d,我更改了它,因为当前文档在新代码中推荐np.isin
  • 显然版本 1.11.0,'in1d' 目前适用于我。不知道如何在不破坏当前安装的 python 2.7 的情况下仅升级 numpy。
【解决方案2】:

【讨论】:

  • 这是一个有趣的想法,因为有时当我使用 'numpy.where' 之类的东西时,我会得到一个我没想到的数组元组,这会导致一些问题。不能把它弄平,但我试着按情况压扁那些。如果我展平整个 2D 数组,我会得到一个非常长(当然长三倍)的数组,它没有匹配的索引,但我可能会 div 值以取回原始索引。无论哪种方式,我认为我都可以使用我已经通过“numpy.where”函数得出的真值表来对抗原始数组。打算试试看,看看我得到了什么。