首页 > 解决方案 > Numpy Sum Rows of 2D Array 唯一(无序列重复)

问题描述

我有以下数组

import numpy as np

single_array =
[[ 1 80 80 80]
 [ 2 80 80 89]
 [ 3 52 50 90]
 [ 4 39 34 54]
 [ 5 37 47 32]
 [ 6 42 42 27]
 [ 7 42 52 27]
 [ 8 38 33 28]
 [ 9 42 37 42]]

并希望在此 single_array 中创建另一个具有 2 行的所有唯一总和的数组,以便 1+2 和 2+1 被视为重复项并且仅包含一次。

首先,我想更新数组的第 0 列以将每个值乘以 10(这样我就可以识别相应的匹配项),然后我想将每 2 行相加并将它们附加到新数组中。

输出应如下所示:

double_array=
[[12 160 160 169]
 [13 132 130 170]
 [14 119 114 134]
...
 [98 80 70 70]]

我可以使用 itertools.combinations 获取具有两个唯一组合的 3D 数组,然后在相应的第 3 轴上添加行吗?

标签: arrayspython-3.xnumpy

解决方案


这个

import numpy as np
from itertools import combinations

single_array = np.array(
[[ 1, 80, 80, 80],
 [ 2, 80, 80, 89],
 [ 3, 52, 50, 90],
 [ 4, 39, 34, 54],
 [ 5, 37, 47, 32],
 [ 6, 42, 42, 27],
 [ 7, 42, 52, 27],
 [ 8, 38, 33, 28],
 [ 9, 42, 37, 42]]
)

np.vstack([single_array[i] * np.array([10, 1, 1, 1]) + single_array[j] 
           for i, j in combinations(range(single_array.shape[0]), 2)])

根据指定的输入和输出做你所要求的;我不确定这是否是您真正需要的。我认为它不会扩展到大投入。

找到这个总和的 3D 数组将是参差不齐的(第一个“层”深度为 9,下一层为 8,等等);你也许可以用 NaN 或掩码来解决这个问题。对于大输入,它也不能很好地扩展:您将分配两倍于您需要的内存,然后必须索引不规则的层以获得最终输出。

如果您必须为大数组快速执行此操作,我建议使用预先分配的输出数组和带有Numba的 for 循环:

from numba import jit

@jit(nopython=True)
def unique_row_sums(a):
    n = a.shape[0]
    b = np.empty((n*(n-1)//2, a.shape[1]))
    s = np.array([10, 1, 1, 1])
    k = 0
    for i in range(n):
        for j in range(i+1, n):
            b[k] = s * a[i] + a[j]
            k += 1
    return b

在我对 IPython 的不太仔细的测试中,%timeit使用您的数据的基于 itertools 的版本大约需要 4µs 和 152µs,并且应该可以更好地扩展。


推荐阅读