【问题标题】:How can I find indexes with same elements in 2d numpy array?如何在 2d numpy 数组中找到具有相同元素的索引?
【发布时间】:2020-10-07 17:55:26
【问题描述】:

我正在从事一个机器视觉项目。通过在图片上反射激光,我在 Opencv 的帮助下检测到激光落在图片上的像素。我将这些像素值保存为 2d numpy 数组。但是,我想通过确定x轴值相同的像素值并取它们的平均值来使x,y值唯一。像素值顺序保存在numpy数组中。

例如:

[[659 253]
 [660 253]
 [660 256]
 [661 253]
 [662 253]
 [663 253]
 [664 253]
 [665 253]]

首先,我的目标是找出每个列表的第一个元素相同的所有列表。使用 Opencv 时,像素值保存在 numpy 数组中以更有用。我正在尝试自己编写索引方法。我为自己创建了一个 numpy 数组以使其更简单。

x = np.array([[1, 2], [1, 78], [1, 3], [1, 6], [4, 3], [5, 6], [5, 3]], np.int32)

我按照这样的方法从x数组的列表中查找第一个元素相同的值。

for i in range (len (x)):
        if x [i]! = x [-1] and x [i] [0] == x [i + 1] [0]:
            print (x [i], x [i + 1])

我想通过浏览 x 数组列表来检查第一个列表中的第一个元素是否在下一个列表中。为了不遇到索引超出范围错误,我使用了x [i]! = x [-1]。我期待这个循环将以下结果返回给我。

[1,2] [1,78]
[1,78] [1,3]
[1,3] [1,6]
[5,6] [5,3]

我稍后会从列表中删除重复的元素,但我得到了

ValueError:具有多个元素的数组的真值不明确。使用a.any()或a.all()

我不熟悉 numpy 数组,所以我无法得到我想要的解决方案。是否可以使用 numpy 数组方法获得我想要的结果?感谢您的宝贵时间。

【问题讨论】:

  • 显示您用于获取该错误的方法。
  • 我在问 numpy 数组方法。不是python方法。我没有使用任何 numpy 数组方法。
  • 你能说明你做了什么来得到这个错误吗?它将帮助我帮助您解决这个问题。这通常也是良好的做法和普遍的礼貌。它不必是什么花哨的东西。我只是想知道你的头在哪里可以这么说。
  • 我只是试试这个。 for i in range(len(x)): if x[i] != x[-1] and x[i][0] == x[i+1][0]: print(x[i], x[i+1])
  • 我已经起草了一个答案。我会在你edited 发帖后发布。

标签: python arrays numpy


【解决方案1】:

方法 1

这是一种 numpy 方法:

x_sorted = x[np.argsort(x[:,0])]
marker_idx = np.flatnonzero(np.diff(x_sorted[:,0]))+1
output = np.split(x_sorted, marker_idx)

方法 2

您还可以使用包numpy_indexed,它旨在以更少的脚本和不损失性能来解决groupby问题:

import numpy_indexed as npi
npi.group_by(x[:, 0]).split(x)

方法 3

您可以获取索引组,但这可能不是最佳选择,因为列表理解:

import pandas as pd
[x[idx] for idx in pd.DataFrame(x).groupby([0]).indices.values()]

输出

[array([[  1,   2],
       [  1,  78],
       [  1,   3],
       [  1,   6],
       [  1, 234]]), 
array([[4, 3]]), 
array([[5, 6],
       [5, 3]])]

【讨论】:

  • 我已经通过方法 1 达到了我想要的结果。 np.flatnonzero (np.diff (x_sorted [:, 0])) + 1 行的工作很棒。如果没有你的帮助,我会在这里浪费很多时间。非常感谢。我会将此答案标记为解决方案。
【解决方案2】:

使用 itertools.groupby 尝试以下操作:

x.sort(axis=0)
for l in [list([tuple(p) for p in k]) for i,k in itertools.groupby(x, key=lambda x: x[0])]:
    print(l)

输出:

[(1, 2), (1, 3), (1, 4), (1, 5), (1, 6)]
[(3, 6), (3, 78)]
[(5, 234)]

【讨论】:

    【解决方案3】:

    您可以使用np.unique 及其return_inverse 参数(实际上是一个排序索引)和return_counts,这将有助于构建分割点:

    _, ind, cnt = np.unique(x[:, 0], return_index=True, return_counts=True)
    

    索引iu 排列成x。要以另一种方式排序,您需要反转索引。幸运的是,np.argsort 是它自己的逆:

    ind = np.argsort(ind)
    

    要获取数据的分割点,可以在计数上使用np.cumsum。您不需要最后一个元素,因为它总是会标记数组的结尾:

    spp = np.cumsum(cnt[:-1])
    

    最后,您可以使用np.split 来获取您想要的子数组列表:

    result = np.split(x[ind, :], spp, axis=0)
    

    TL;DR

    _, ind, cnt = np.unique(x[:, 0], return_index=True, return_counts=True)
    np.split(x[np.argsort(ind), :], np.cumsum(cnt[:-1]), axis=0)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-10-13
      • 2022-01-08
      • 1970-01-01
      • 2017-08-04
      • 1970-01-01
      • 2019-07-12
      • 1970-01-01
      相关资源
      最近更新 更多