【问题标题】:Count all values in a matrix less than a value计算矩阵中大于某个值的所有值
【发布时间】:2012-10-11 08:21:27
【问题描述】:

我必须计算矩阵(二维数组)中大于 200 的所有值。

我为此写下的代码是:

za=0   
p31 = numpy.asarray(o31)   
for i in range(o31.size[0]):   
    for j in range(o32.size[1]):   
        if p31[i,j]<200:   
            za=za+1   
print za

o31 是一个图像,我将其转换为矩阵,然后查找值。

我的问题是,有没有更简单的方法来做到这一点?

【问题讨论】:

  • 这不只是打印小于 200 的值的数量,而不是实际值吗?
  • 是的。我只需要所有值的总和,而不是实际值本身。
  • 这里也没有得到总数。将za 设置为空列表za = [],然后设置za.append(p31[i,j]),最后退出for 循环,print sum(za);但我确信有更好的方法,因为您使用的是 numpy。
  • 我更新了您的问题标题,以使您的问题更清楚(我从 cmets 和答案中了解到。如果有误,您可以重新编辑。

标签: python arrays coding-style numpy pixel


【解决方案1】:

这对于布尔数组来说非常简单:

p31 = numpy.asarray(o31)
za = (p31 < 200).sum() # p31<200 is a boolean array, so `sum` counts the number of True elements

【讨论】:

  • 我认为这应该是最佳答案。 np.where 也很明显,但提供了此处不需要的其他信息,使答案不那么简单,性能也稍慢
【解决方案2】:

numpy.where 函数是您的朋友。因为它的实现是为了充分利用数组数据类型,所以对于大图像,您应该注意到比您提供的纯 python 解决方案的速度有所提高。

直接使用 numpy.where 将产生一个布尔掩码,指示某些值是否符合您的条件:

>>> data
array([[1, 8],
       [3, 4]])
>>> numpy.where( data > 3 )
(array([0, 1]), array([1, 1]))

而掩码可以直接用来索引数组,得到实际值:

>>> data[ numpy.where( data > 3 ) ]
array([8, 4])

从那里获取结果的确切位置取决于您希望结果的形式。

【讨论】:

  • 谢谢...但是我需要值的总数,而不是值本身。我应该 sum(numpy.where(data
  • 如果你想要数值的数量,而不是总和,你会做 len(numpy.where(data
  • 如果条件变为> 0,则返回(array([0, 0, 1, 1]), array([0, 1, 0, 1])),它是做什么的意思是?还是一个错误?
  • 这种方法过于复杂。 @neonneo 的方法更直接,并且在回答问题方面做得更好。
  • @jimh for me np.where 返回一个元组,必须做 len(np.where(...)[0])
【解决方案3】:

有很多方法可以实现这一点,例如扁平化过滤或简单枚举,但我认为使用 Boolean/mask array 是最简单的一种(而 iirc 是一种更快的方法):

>>> y = np.array([[123,24123,32432], [234,24,23]])
array([[  123, 24123, 32432],
       [  234,    24,    23]])
>>> b = y > 200
>>> b
array([[False,  True,  True],
       [ True, False, False]], dtype=bool)
>>> y[b]
array([24123, 32432,   234])
>>> len(y[b])
3
>>>> y[b].sum()
56789

更新

正如 nneonneo 已经回答的那样,如果您想要的只是通过阈值的元素数量,您可以简单地这样做:

>>>> (y>200).sum()
3

这是一个更简单的解决方案。


filter的速度对比:

### use boolean/mask array ###

b = y > 200

%timeit y[b]
100000 loops, best of 3: 3.31 us per loop

%timeit y[y>200]
100000 loops, best of 3: 7.57 us per loop

### use filter ###

x = y.ravel()
%timeit filter(lambda x:x>200, x)
100000 loops, best of 3: 9.33 us per loop

%timeit np.array(filter(lambda x:x>200, x))
10000 loops, best of 3: 21.7 us per loop

%timeit filter(lambda x:x>200, y.ravel())
100000 loops, best of 3: 11.2 us per loop

%timeit np.array(filter(lambda x:x>200, y.ravel()))
10000 loops, best of 3: 22.9 us per loop

*** use numpy.where ***

nb = np.where(y>200)
%timeit y[nb]
100000 loops, best of 3: 2.42 us per loop

%timeit y[np.where(y>200)]
100000 loops, best of 3: 10.3 us per loop

【讨论】:

  • timeit y[b] 省略了过滤器计算中的一半代码。 %timeit y[y&gt;200] 是等价的。
【解决方案4】:

这是一个变体,它使用花哨的索引并将实际值作为中间值:

p31 = numpy.asarray(o31)
values = p31[p31<200]
za = len(values)

【讨论】:

  • 这只是常规的布尔索引。
【解决方案5】:

要计算任何 numpy 数组中大于 x 的值的数量,您可以使用:

n = len(matrix[matrix > x])

布尔索引返回一个数组,该数组仅包含满足条件(矩阵> x)的元素。然后 len() 计算这些值。

【讨论】:

  • 您可能需要解释为什么这样做。重载__gt__ 我猜,但这并不明显。
【解决方案6】:

您可以使用numpy.count_nonzero,将整体转换为单行:

za = numpy.count_nonzero(numpy.asarray(o31)<200)  #as written in the code

【讨论】:

  • 您可以避免使用np.count_nonzero(np.less_than(o3, 200)) 显式调用asarray
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-05-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多