例如,对于
a = np.array([[1, 0, 0], [1, 0, 0], [2, 3, 4]])
我想得到
[2, 2, 3]
有没有办法不用for循环或使用np.vectorize
?
编辑:实际数据由1000行组成,每行100个元素,每个元素的范围从1到365。最终目标是确定有重复的行的百分比。这是一个作业问题,我已经解决了(用for循环),但我只是想知道是否有更好的方法来做它与Numpy。
你愿意考虑熊猫吗?数据帧有一个专门的方法来实现这一点
>>> a = np.array([[1, 0, 0], [1, 0, 0], [2, 3, 4]])
>>> df = pd.DataFrame(a.T)
>>> print(*df.nunique())
2 2 3
此解决方案通过np.apply_沿_轴
实现,它不是矢量化的,并且涉及Python级别的循环。但是使用len
np是相对直观的。独特的
函数。
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]
方法#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的数组。我想创建一个新数组,该数组是每个连续三元组元素的平均值。因此,新数组将是原始数组大小的三分之一。 举个例子: 应该返回数组: 有人可以建议一种有效的方法吗?我在画空白。 问题答案: 如果数组的长度可被3整除: 重塑为高维数组,然后对附加维之一执行某种形式的归约运算是numpy编程的主要内容。
问题内容: 几年前从这个问题开始,在numpy中是否有规范的“移位”功能?我从文档中看不到任何东西。 这是我正在寻找的简单版本: 使用它就像: 这个问题来自于我昨天尝试[编写快速滚动产品的](http://codingdict.com/questions/163825尝试。我需要一种“转移”累积乘积的方法,我所能想到的就是在中复制逻辑。 因此比快得多。此版本的功能执行得更好: 更快的版本只是简单地
如何有效地获取NumPy数组中每个唯一值的频率计数?