Python 按行计算数据数组中的唯一元素

Python 按行计算数据数组中的唯一元素,python,arrays,numpy,Python,Arrays,Numpy,问题的延伸。除了在行上具有唯一的元素外,我还希望具有一个形状类似的数组,该数组提供唯一值的计数。例如,如果初始数组如下所示: a = np.array([[1, 2, 2, 3, 4, 5], [1, 2, 3, 3, 4, 5], [1, 2, 3, 4, 4, 5], [1, 2, 3, 4, 5, 5], [1, 2, 3, 4, 5, 6]]) 我想将其作

问题的延伸。除了在行上具有唯一的元素外,我还希望具有一个形状类似的数组,该数组提供唯一值的计数。例如,如果初始数组如下所示:

a = np.array([[1,  2, 2, 3,  4, 5],
              [1,  2, 3, 3,  4, 5],
              [1,  2, 3, 4,  4, 5],
              [1,  2, 3, 4,  5, 5],
              [1,  2, 3, 4,  5, 6]])
我想将其作为函数的输出:

np.array([[1,  2, 0, 1,  1, 1],
          [1,  1, 2, 0,  1, 1],
          [1,  1, 1, 2,  0, 1],
          [1,  1, 1, 1,  2, 0],
          [1,  1, 1, 1,  1, 1]])

在numpy v.1.9中,似乎有一个额外的参数
return\u counts
,它可以在平坦数组中返回计数。是否有某种方法可以将其重新构造为原始数组维度,其中的值被复制到零处?

此答案背后的思想与此答案非常相似。我在每一行加上一个唯一的虚数。因此,不同行中的两个数字不能相等。因此,只需一次调用
np.unique
,就可以在每行的2D数组中找到所有唯一值

return\u index=True
提供每个唯一值第一次出现的位置时,返回索引
ind

return\u counts=True
给出计数时返回的计数
cnt

将计数放置在每个唯一值第一次出现的位置

这里使用的技巧的一个明显限制是原始数组必须具有int或float数据类型。它不能有一个复杂的数据类型开始,因为每一行乘以一个唯一的虚数可能会产生不同行的重复对


屈服

In [79]: count_unique_by_row(a)
Out[79]: 
array([[1, 2, 0, 1, 1, 1],
       [1, 1, 2, 0, 1, 1],
       [1, 1, 1, 2, 0, 1],
       [1, 1, 1, 1, 2, 0],
       [1, 1, 1, 1, 1, 1]])

该方法与np.unique对每一行执行相同的操作,方法是对每一行进行排序并获得连续相等值的长度。它的复杂性为O(NMlog(M)),这比在整个阵列上运行unique要好,因为它的复杂性为O(NM(log(NM))

运行时间:

In [162]: b = np.random.random(size=100000).reshape((100, 1000))

In [163]: %timeit row_unique_count(b)
100 loops, best of 3: 10.4 ms per loop

In [164]: %timeit count_unique_by_row(b)
100 loops, best of 3: 19.4 ms per loop

In [165]: assert np.all(row_unique_count(b) == count_unique_by_row(b))

非常有趣。
undravel_index
到底是如何工作的?
ind
是一个一维数组,这个函数似乎可以将其转换为与
a
兼容的二维索引……我最近写了一点。另请参见。实际上,我刚刚意识到这里不需要
undravel_index
np.put
可以放置
c使用
ind
平面索引直接将nt
值转换为
b
。我将编辑帖子以显示我的意思。您对
unravel\u index
所做操作的猜测完全正确。返回N维数组的平面1D视图。
ind
中的索引是指向
a
平面1D视图的索引。
unravel\u index
将这些索引转换为相应的坐标索引,您可以使用这些索引将其索引到N维数组
a
def row_unique_count(a):                                    
     args = np.argsort(a)
     unique = a[np.indices(a.shape)[0], args]
     changes = np.pad(unique[:, 1:] != unique[:, :-1], ((0, 0), (1, 0)), mode="constant", constant_values=1)
     idxs = np.nonzero(changes)
     tmp = np.hstack((idxs[-1], 0))
     counts = np.where(tmp[1:], np.diff(tmp), a.shape[-1]-tmp[:-1])
     count_array = np.zeros(a.shape, dtype="int")
     count_array[(idxs[0], args[idxs])] = counts
     return count_array
In [162]: b = np.random.random(size=100000).reshape((100, 1000))

In [163]: %timeit row_unique_count(b)
100 loops, best of 3: 10.4 ms per loop

In [164]: %timeit count_unique_by_row(b)
100 loops, best of 3: 19.4 ms per loop

In [165]: assert np.all(row_unique_count(b) == count_unique_by_row(b))