当前位置: 首页 > 知识库问答 >
问题:

NumPy数组中每行的唯一元素数

别锐
2023-03-14

例如,对于

a = np.array([[1, 0, 0], [1, 0, 0], [2, 3, 4]])

我想得到

[2, 2, 3]

有没有办法不用for循环或使用np.vectorize

编辑:实际数据由1000行组成,每行100个元素,每个元素的范围从1到365。最终目标是确定有重复的行的百分比。这是一个作业问题,我已经解决了(用for循环),但我只是想知道是否有更好的方法来做它与Numpy。

共有3个答案

孙乐逸
2023-03-14

你愿意考虑熊猫吗?数据帧有一个专门的方法来实现这一点

>>> a = np.array([[1, 0, 0], [1, 0, 0], [2, 3, 4]])
>>> df = pd.DataFrame(a.T)
>>> print(*df.nunique())
2 2 3
郎鸿
2023-03-14

此解决方案通过np.apply_沿_轴实现,它不是矢量化的,并且涉及Python级别的循环。但是使用lennp是相对直观的。独特的函数。

import numpy as np
from toolz import compose

a = np.array([[1, 0, 0], [1, 0, 0], [2, 3, 4]])

np.apply_along_axis(compose(len, np.unique), 1, a)    # [2, 2, 3]

龚承嗣
2023-03-14

方法#1

一种带排序的矢量化方法-

In [8]: b = np.sort(a,axis=1)

In [9]: (b[:,1:] != b[:,:-1]).sum(axis=1)+1
Out[9]: array([2, 2, 3])

进近#2

对于不是很大的int,另一种方法是用偏移量抵消每行,偏移量将每行的元素与其他元素区分开来,然后进行二进制求和和计算每行的非零箱数-

n = a.max()+1
a_off = a+(np.arange(a.shape[0])[:,None])*n
M = a.shape[0]*n
out = (np.bincount(a_off.ravel(), minlength=M).reshape(-1,n)!=0).sum(1)

作为函数逼近-

def sorting(a):
    b = np.sort(a,axis=1)
    return (b[:,1:] != b[:,:-1]).sum(axis=1)+1

def bincount(a):
    n = a.max()+1
    a_off = a+(np.arange(a.shape[0])[:,None])*n
    M = a.shape[0]*n
    return (np.bincount(a_off.ravel(), minlength=M).reshape(-1,n)!=0).sum(1)

# From @wim's post   
def pandas(a):
    df = pd.DataFrame(a.T)
    return df.nunique()

# @jp_data_analysis's soln
def numpy_apply(a):
    return np.apply_along_axis(compose(len, np.unique), 1, a) 

案例#1:方形

In [164]: np.random.seed(0)

In [165]: a = np.random.randint(0,5,(10000,10000))

In [166]: %timeit numpy_apply(a)
     ...: %timeit sorting(a)
     ...: %timeit bincount(a)
     ...: %timeit pandas(a)
1 loop, best of 3: 1.82 s per loop
1 loop, best of 3: 1.93 s per loop
1 loop, best of 3: 354 ms per loop
1 loop, best of 3: 879 ms per loop

案例2:大量行

In [167]: np.random.seed(0)

In [168]: a = np.random.randint(0,5,(1000000,10))

In [169]: %timeit numpy_apply(a)
     ...: %timeit sorting(a)
     ...: %timeit bincount(a)
     ...: %timeit pandas(a)
1 loop, best of 3: 8.42 s per loop
10 loops, best of 3: 153 ms per loop
10 loops, best of 3: 66.8 ms per loop
1 loop, best of 3: 53.6 s per loop

扩展到每列的唯一元素数

为了扩展,我们只需要沿着两个提议的方法的另一个轴进行切片和ufunc操作,就像这样-

def nunique_percol_sort(a):
    b = np.sort(a,axis=0)
    return (b[1:] != b[:-1]).sum(axis=0)+1

def nunique_percol_bincount(a):
    n = a.max()+1
    a_off = a+(np.arange(a.shape[1]))*n
    M = a.shape[1]*n
    return (np.bincount(a_off.ravel(), minlength=M).reshape(-1,n)!=0).sum(1)

让我们看看如何扩展到泛型维度的数组,并获得沿着泛型轴的唯一计数数。我们将使用np.diff及其参数来获得这些连续的差异,从而使其具有通用性,如下所示-

def nunique(a, axis):
    return (np.diff(np.sort(a,axis=axis),axis=axis)!=0).sum(axis=axis)+1

样本运行-

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

In [78]: nunique(a, axis=0)
Out[78]: array([3, 2, 3, 2, 3])

In [79]: nunique(a, axis=1)
Out[79]: array([3, 3, 2, 3, 3])

如果您使用的是浮动pt编号,并且希望基于某个公差值而不是绝对匹配来生成唯一性大小写,我们可以使用np.isclose。有两个这样的选择-

(~np.isclose(np.diff(np.sort(a,axis=axis),axis=axis),0)).sum(axis)+1
a.shape[axis]-np.isclose(np.diff(np.sort(a,axis=axis),axis=axis),0).sum(axis)

对于自定义公差值,使用np.isclose输入这些值。

 类似资料:
  • 问题内容: 在最近的一次采访中有人问我这个问题。 您将获得一个包含一百万个元素的数组。除了一个元素外,所有元素都是重复的。我的任务是找到独特的元素。 我的做法是要经过在整个数组循环,然后创建一个索引作为数组中和的数组中出现的次数。然后再次遍历我们的地图,并返回值为1的索引。 我说我的方法会花费时间。面试官告诉我要以低于复杂度的方式对其进行优化。我说过,我们不能,因为我们必须遍历具有一百万个元素的整

  • 问题内容: 在Python中,我们可以使用来获取数组中值的索引。 但是,当我尝试执行NumPy数组时: 我得到: AttributeError:“ numpy.ndarray”对象没有属性“ index” 我如何在NumPy数组上执行此操作? 问题答案: 使用来获得,其中一个给定的条件是指数。 例子: 对于称为的2D : 对于一维数组: 请注意,这也适用于像条件,,等等… 您也可以使用方法创建的子

  • 问题内容: 我有两个一维数组x和y,一个比另一个小。我试图找到x中y的每个元素的索引。 我发现有两种简单的方法可以做到这一点,第一种很慢,第二种需要占用大量内存。 记忆猪 是否有更快的方法或更少的内存密集型方法?理想情况下,搜索将利用以下事实:我们不是在列表中搜索一件事,而是在搜索许多东西,因此稍微适合并行化。如果您不假设y的每个元素实际上都在x中,则可获得加分。 问题答案: 正如Joe King

  • 问题内容: 几年前从这个问题开始,在numpy中是否有规范的“移位”功能?我从文档中看不到任何东西。 这是我正在寻找的简单版本: 使用它就像: 这个问题来自于我昨天尝试[编写快速滚动产品的](http://codingdict.com/questions/163825尝试。我需要一种“转移”累积乘积的方法,我所能想到的就是在中复制逻辑。 因此比快得多。此版本的功能执行得更好: 更快的版本只是简单地

  • 问题内容: 我有一个numpy的数组。我想创建一个新数组,该数组是每个连续三元组元素的平均值。因此,新数组将是原始数组大小的三分之一。 举个例子: 应该返回数组: 有人可以建议一种有效的方法吗?我在画空白。 问题答案: 如果数组的长度可被3整除: 重塑为高维数组,然后对附加维之一执行某种形式的归约运算是numpy编程的主要内容。

  • 如何有效地获取NumPy数组中每个唯一值的频率计数?