【问题标题】:Get indices for values of one array in another array获取另一个数组中一个数组的值的索引
【发布时间】:2018-03-28 02:08:54
【问题描述】:

我有两个包含相同值集的一维数组,但顺序不同。我想找到索引列表,它根据另一个数组重新排序一个数组。例如,我的 2 个数组是:

ref = numpy.array([5,3,1,2,3,4])
new = numpy.array([3,2,4,5,3,1])

我想要order 的列表new[order] == ref

我目前的想法是:

def find(val):
    return numpy.argmin(numpy.absolute(ref-val))

order = sorted(range(new.size), key=lambda x:find(new[x]))

但是,这仅适用于没有重复值的情况。在我的示例中,3 出现了两次,我得到了new[order] = [5 3 3 1 2 4]。第二个3 直接放在第一个之后,因为我的函数val() 不跟踪我当前正在寻找的3

所以我可以添加一些东西来解决这个问题,但我觉得可能会有更好的解决方案。也许在某个库(NumPy 或 SciPy)中?

关于重复的编辑:这个linked solution 假定数组是有序的,或者对于“无序”解决方案,返回重复的索引。我需要每个索引在order 中只出现一次。然而,哪个先出现并不重要(根据提供的数据,这两者都不可能)。

我用sort_idx = A.argsort(); order = sort_idx[np.searchsorted(A,B,sorter = sort_idx)] 得到的是:[3, 0, 5, 1, 0, 2]。但我要找的是[3, 0, 5, 1, 4, 2]

【问题讨论】:

  • 如果元素重复,你得到哪个索引真的很重要吗?除了a[ind] 之外,您还想做什么来获得b
  • 话虽如此,是的,有一种方法可以使用多个 argsort。等我到了真正的电脑上,我就写出来。
  • @Divakar。这不是同一个问题。它要求找到洗牌的索引,而不是子集。因此,使用 argsort 可以进行很好的优化,但不适用于其他问题。我希望你支持我重新开张的提议。
  • @MadPhysicist 不确定您指的是哪个子集。那里的 searchsorted 解决方案给出了索引,这是这个问题中预期的order。您是否尝试过该解决方案?
  • @Divakar 我试过了,我在order 中得到了一些多个索引(见编辑)。

标签: numpy


【解决方案1】:

鉴于refnew 是彼此的洗牌版本,我们可以使用两个数组的排序版本和invertibilitynp.argsort

开始于:

i = np.argsort(ref)
j = np.argsort(new)

现在ref[i]new[j] 都给出了数组的排序版本,两者都是一样的。您可以通过执行以下操作来反转第一种排序:

k = np.argsort(i)

现在ref 只是new[j][k]new[j[k]]。由于所有操作都是使用唯一索引的随机播放,因此最终索引 j[k] 也是唯一的。 j[k] 可以一步计算出来

order = np.argsort(new)[np.argsort(np.argsort(ref))]

从你原来的例子:

>>> ref = np.array([5, 3, 1, 2, 3, 4])
>>> new = np.array([3, 2, 4, 5, 3, 1])
>>> np.argsort(new)[np.argsort(np.argsort(ref))]
>>> order
array([3, 0, 5, 1, 4, 2])
>>> new[order]  # Should give ref
array([5, 3, 1, 2, 3, 4])

这可能并不比similar question on SO 的更通用解决方案快,但它确实保证了您要求的唯一索引。进一步的优化是用this answer 中的argsort_unique 函数替换np.argsort(i)。我会更进一步,只计算排序的倒数:

def inverse_argsort(a):
    fwd = np.argsort(a)
    inv = np.empty_like(fwd)
    inv[fwd] = np.arange(fwd.size)
    return inv

order = np.argsort(new)[inverse_argsort(ref)]

【讨论】:

  • 这个想法似乎是正确的。为了进一步优化它,我们可以使用argsort_unique 得到k
  • @Divakar。我将其添加到答案中。
  • @Feodoran。我明白你编辑的目的。我破坏了它,但会更新自己。
  • 很好,谢谢。起初我有点担心打电话三次argsort。但是inverse_argsort 对此进行了很好的优化,速度提高了一倍以上。
  • @Feodoran。如果您将 argsort 替换为对 lexsort 的适当调用,则反转函数将正常工作。
猜你喜欢
  • 2021-06-24
  • 2021-11-24
  • 2016-05-26
  • 1970-01-01
  • 2022-07-05
  • 1970-01-01
  • 2013-08-14
  • 2023-01-30
  • 1970-01-01
相关资源
最近更新 更多