【问题标题】:create intersection from two or more 2d numpy arrays based on common value in one column根据一列中的公共值从两个或多个 2d numpy 数组创建交集
【发布时间】:2012-01-23 16:31:39
【问题描述】:

我有 3 个具有以下结构的 numpy 重新数组。 第一列是某个位置(整数),第二列是分数(浮点数)。

输入:

a = [[1, 5.41],
     [2, 5.42],
     [3, 12.32],
     dtype=[('position', '<i4'), ('score', '<f4')])
     ]

b = [[3, 8.41],
     [6, 7.42],
     [4, 6.32],
     dtype=[('position', '<i4'), ('score', '<f4')])
     ]

c = [[3, 7.41],
     [7, 6.42],
     [1, 5.32],
     dtype=[('position', '<i4'), ('score', '<f4')])
     ]

所有 3 个数组都包含相同数量的元素。
我正在寻找一种基于位置列将这三个二维数组组合成一个数组的有效方法。

上述示例的输出数组应如下所示:

输出:

output = [[3, 12.32, 8.41, 7.41],
          dtype=[('position', '<i4'), ('score1', '<f4'),('score2', '<f4'),('score3', '<f4')])]

只有位置为 3 的行在输出数组中,因为该位置出现在所有 3 个输入数组中。

更新:我的幼稚方法是以下步骤:

  1. 为我的 3 个输入数组的第一列创建向量。
  2. 使用 intersect1D 得到这 3 个向量的交集。
  3. 以某种方式检索所有 3 个输入数组的向量的索引。
  4. 使用 3 个输入数组中的过滤行创建新数组。

更新2: 每个位置值可以在一个、两个或所有三个输入数组中。在我的输出数组中,我只想包含所有 3 个输入数组中出现的位置值的行。

【问题讨论】:

  • 如果它导致位置具有不同数量的值,所以数组会变形?
  • 我不确定我是否理解。我可以保证 3 个输入数组始终具有相同的形状/结构 (N,1),在我的情况下,我始终有 3 个输入数组。输出数组的形状应为 (X,4)
  • 那么数组要么全部包含一个值,要么没有包含一个值?即你不会得到 2/3 包含一个值?另外,您能否编辑问题以创建数组,而不是显示 repr?
  • 不,可能只有一两个包含位置值。但是,在输出数组中,我只想包含在所有 3 个输入数组中都有位置值的行。我更新了问题以使其更清晰

标签: python arrays numpy set intersection


【解决方案1】:

这是一种方法,我相信它应该相当快。我认为您要做的第一件事是计算每个位置的出现次数。这个函数将处理:

def count_positions(positions):
    positions = np.sort(positions)
    diff = np.ones(len(positions), 'bool')
    diff[:-1] = positions[1:] != positions[:-1]
    count = diff.nonzero()[0]
    count[1:] = count[1:] - count[:-1]
    count[0] += 1
    uniqPositions = positions[diff]
    return uniqPositions, count

现在使用上面的函数形式,您只想占据出现 3 次的位置:

positions = np.concatenate((a['position'], b['position'], c['position']))
uinqPos, count = count_positions(positions)
uinqPos = uinqPos[count == 3]

我们将使用搜索排序,因此我们对 a b 和 c 进行排序:

a.sort(order='position')
b.sort(order='position')
c.sort(order='position')

现在我们可以通过用户搜索排序来查找每个数组中的哪个位置来找到我们的每个 uniqPos:

new_array = np.empty((len(uinqPos), 4))
new_array[:, 0] = uinqPos
index = a['position'].searchsorted(uinqPos)
new_array[:, 1] = a['score'][index]
index = b['position'].searchsorted(uinqPos)
new_array[:, 2] = b['score'][index]
index = c['position'].searchsorted(uinqPos)
new_array[:, 3] = c['score'][index]

使用字典可能有一个更优雅的解决方案,但我首先想到了这个,所以我将把它留给其他人。

【讨论】:

    猜你喜欢
    • 2017-05-04
    • 2023-03-18
    • 1970-01-01
    • 2020-10-02
    • 2021-08-15
    • 2011-06-05
    • 2013-10-10
    • 2011-04-06
    • 1970-01-01
    相关资源
    最近更新 更多