使用'if'比较两个numpy数组的值

6 投票
5 回答
12502 浏览
提问于 2025-04-20 20:04

我对numpy数组还比较陌生,最近在比较两个数组的时候遇到了问题。

我有两个数组,内容如下:

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

我想做的事情大概是这样的:

if b > a:
    c = b
else:
    c = a

这样我最后得到的数组应该是c = np.array([2,4,3,5,5])。

其实可以理解为从这两个数组中每个位置取最大的值。

不过,我遇到了一个错误:

ValueError: The truth value of an array with more than one element is ambiguous. 
Use a.any() or a.all(). 

我试过一些方法,但不太确定这些方法是否适合我想要的结果。

有没有人能给我一些建议,帮我解决这个问题呢?

5 个回答

0

这可能不是最有效的方法,但这是一个更适合原问题的答案:

import numpy as np

c = np.zeros(shape=(5,1))

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

for i in range(5):
    if b.item(i) > a.item(i):
        c[i] = b.item(i)
    else:
        c[i] = a.item(i) 
1

以下方法也可以使用:

  1. 使用 numpy.maximum

    >>> np.maximum(a, b)

  2. 使用 numpy.maxnumpy.vstack

    >>> np.max(np.vstack(a, b), axis = 0)

2

这里有另一种实现这个目标的方法

c = np.array([y if y>z else z for y,z in zip(a,b)])
6

在numpy中,几乎所有的比较都是逐个元素进行的,这样会返回一个完整的数组:

>>> b > a
array([ True,  True, False,  True, False], dtype=bool)

那么,这个结果是对还是错呢?在if语句中应该怎么处理它呢?

numpy的做法是,它不会去猜测,而是直接抛出一个异常。

如果你想认为只要有一个值为真就算是真的,可以使用any

>>> if np.any(b > a): print('Yes!')
Yes!

如果你想认为只有当所有值都为真时才算是真的,可以使用all

>>> if np.all(b > a): print('Yes!')

不过我敢肯定你并不想用这两种方法。你想要的是对整个数组进行if/else的操作。

当然,你可以把单个值的if/else逻辑放在一个函数里,然后明确地用vectorize它并调用:

>>> def mymax(a, b):
...     if b > a:
...         return b
...     else:
...         return a
>>> vmymax = np.vectorize(mymax)
>>> vmymax(a, b)
array([2, 4, 3, 5, 5])

这确实是个值得了解的方法……但很少有人会这样做。通常有更间接的方法可以用原生的向量化函数来实现——而且往往还有更直接的方法。


一种间接的方法是利用真和假分别对应数字1和0的事实:

>>> (b>a)*b + (b<=a)*a
array([2, 4, 3, 5, 5])

b>a时,这个表达式会计算1*b[i] + 0*a[i],而当b<=a时,它会计算0*b[i] + 1*a[i]。虽然有点复杂,但理解起来并不难。还有更清晰但更冗长的写法。

不过我们来找一个更好、更直接的解决方案。


首先,注意到你的mymax函数对于两个值来说,和Python内置的max函数是完全一样的:

>>> vmymax = np.vectorize(max)
>>> vmymax(a, b)
array([2, 4, 3, 5, 5])

然后考虑一下,对于这么有用的功能,numpy可能已经有现成的了。快速搜索一下就能找到maximum

>>> np.maximum(a, b)
array([2, 4, 3, 5, 5])
15

你在寻找一个叫做 np.fmax 的函数。这个函数的作用是比较两个数组中的每个元素,找出每对元素中较大的那个,同时会忽略掉那些是NaN(不是一个数字)的值。

import numpy as np
a = np.array([1, 2, 3, 4, 5])
b = np.array([2, 4, 3, 5, 2])
c = np.fmax(a, b)

输出结果是

array([2, 4, 3, 5, 5])

撰写回答