numpy 如何在使用np.linspace时实现多值函数?

u3r8eeie  于 12个月前  发布在  其他
关注(0)|答案(3)|浏览(118)

我有一个多值函数,我想和np. linspace一起使用。每当函数中有if/else条件时,我都会得到一个值错误。
我期望将函数f应用于np.linspace类似于以下MWE中的Map:

def f(n):
    if n < 3 or n > 5:
        return 0
    else:
        return n

a = list(range(0, 11))
print(a)
print(list(map(f, a)))

b = np.linspace(0, 10, 11)
print(b)
print(f(b))

字符串
这对于常规列表很有效,但对于np.linspace则会失败,错误为

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


看来我弄错了,np.linspace出于某种原因想要检查数组中的每个元素是否满足条件。我不想使用any()或all(),因为那不是我想要做的。什么是最好的方法?

ygya80vv

ygya80vv1#

你需要使用一个面具,例如:

b = np.linspace(0, 10, 11)
mask = np.logical_or(b < 3, b > 5)
b[mask] = 0

字符串

shstlldc

shstlldc2#

有多种方法可以以矢量化的方式完成此任务:

使用np.where

def f1(n):
    return np.where((n < 3) | (n > 5), 0, n)

b = np.linspace(0, 10, 11)
f1(b)

字符串

使用乘法:

def f2(n):
    return n*(n >= 3)*(n <= 5)
f2(b)

oprakyz7

oprakyz73#

你的函数是用单个数字编写的,将n与3或5进行比较:

In [129]: def f(n):
     ...:     if n < 3 or n > 5:
     ...:         return 0
     ...:     else:
     ...:         return n
     ...:         

In [130]: f(1), f(4)
Out[130]: (0, 4)

字符串
Python有许多generators,它们设置了一个计算或迭代,但实际上并不执行它。你必须把它们 Package 在list(或一些for循环)中来填充它们:

In [131]: range(1,5)
Out[131]: range(1, 5)

In [133]: a=list(range(1,5)); a
Out[133]: [1, 2, 3, 4]


你不能给予你的函数一个列表:

In [134]: f(a)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[134], line 1
----> 1 f(a)

Cell In[129], line 2, in f(n)
      1 def f(n):
----> 2     if n < 3 or n > 5:
      3         return 0
      4     else:

TypeError: '<' not supported between instances of 'list' and 'int'


换句话说,[1,2,3,4]<3不工作。
map是另一个generator,它需要列表:

In [135]: map(f, a)
Out[135]: <map at 0x1e01f85aa40>

In [136]: list(map(f, a))
Out[136]: [0, 0, 3, 4]


生成器可以串在一起,而无需将每个中间步骤转换为列表:

In [137]: list(map(f, range(1,5)))
Out[137]: [0, 0, 3, 4]

numpy

numpy有像linspacearange这样的生成numpy数组的函数。它没有“生成器”。

In [143]: b=np.linspace(1,5,5); b
Out[143]: array([1., 2., 3., 4., 5.])


这个数组可以变成一个列表:

In [144]: b.tolist()
Out[144]: [1.0, 2.0, 3.0, 4.0, 5.0]


并通过列表/Map:

In [145]: list(map(f, b.tolist()))
Out[145]: [0, 0, 3.0, 4.0, 5.0]


事实上,数组元素可以“Map”到你的函数:

In [146]: list(map(f, b))
Out[146]: [0, 0, 3.0, 4.0, 5.0]


但是你发现你的函数不能在数组上工作。这是一个不同于列表的错误。
数组可以与一个数字进行比较:

In [149]: b<3
Out[149]: array([ True,  True, False, False, False])


事实上,大多数数学运算符都可以使用数组-加法,等式,幂等。这是数组优于列表的一大好处。
但是if表达式(和or)需要一个true/false,而不是[149]中的数组。这就是为什么你会得到模糊性错误。
可以组合布尔测试(()很重要):

In [152]: ((b<3) | (b>5))
Out[152]: array([ True,  True, False, False, False])


和其他显示可以作为一个多值掩码像你的f工作。np.where是一个方便的工具,但不是唯一的一个。

In [155]: np.where(((b<3) | (b>5)),0,b)
Out[155]: array([0., 0., 3., 4., 5.])


Numpy数组确实有一种“map”迭代,但它内置在数组方法和运算符中。大多数情况下,它是在编译代码中,并且相对较快,特别是对于大型数组。但是有一个显著的学习曲线。你不能有效地将数组替换为列表,或者期望数组像你的map(f...)一样行为。

相关问题