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))