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

u3r8eeie  于 2023-11-18  发布在  其他
关注(0)|答案(3)|浏览(130)

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

  1. def f(n):
  2. if n < 3 or n > 5:
  3. return 0
  4. else:
  5. return n
  6. a = list(range(0, 11))
  7. print(a)
  8. print(list(map(f, a)))
  9. b = np.linspace(0, 10, 11)
  10. print(b)
  11. print(f(b))

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

  1. 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#

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

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

字符串

shstlldc

shstlldc2#

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

使用np.where

  1. def f1(n):
  2. return np.where((n < 3) | (n > 5), 0, n)
  3. b = np.linspace(0, 10, 11)
  4. f1(b)

字符串

使用乘法:

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

展开查看全部
oprakyz7

oprakyz73#

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

  1. In [129]: def f(n):
  2. ...: if n < 3 or n > 5:
  3. ...: return 0
  4. ...: else:
  5. ...: return n
  6. ...:
  7. In [130]: f(1), f(4)
  8. Out[130]: (0, 4)

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

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


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

  1. In [134]: f(a)
  2. ---------------------------------------------------------------------------
  3. TypeError Traceback (most recent call last)
  4. Cell In[134], line 1
  5. ----> 1 f(a)
  6. Cell In[129], line 2, in f(n)
  7. 1 def f(n):
  8. ----> 2 if n < 3 or n > 5:
  9. 3 return 0
  10. 4 else:
  11. TypeError: '<' not supported between instances of 'list' and 'int'


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

  1. In [135]: map(f, a)
  2. Out[135]: <map at 0x1e01f85aa40>
  3. In [136]: list(map(f, a))
  4. Out[136]: [0, 0, 3, 4]


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

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

numpy

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

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


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

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


并通过列表/Map:

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


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

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


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

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


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

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


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

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


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

展开查看全部

相关问题