在numpy.piecewise中使用多个条件块

8
我正在学习模糊系统课程,用电脑记录我的笔记。这意味着我不时需要在电脑上绘制图形。由于这些图形非常明确,我认为使用numpy绘制它们是个好主意(我用LaTeX做笔记,对Python shell也很熟悉,所以我想我能应付得来)。 模糊隶属函数的图形通常是高度分段的,例如:

Fuzzy Membership Function

为了绘制这个图,我尝试使用 numpy.piecewise 的以下代码(但是出现了一个晦涩的错误):
In [295]: a = np.arange(0,5,1)

In [296]: condlist = [[b<=a<b+0.25, b+0.25<=a<b+0.75, b+0.75<=a<b+1] for b in range(3)]
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-296-a951e2682357> in <module>()
----> 1 condlist = [[b<=a<b+0.25, b+0.25<=a<b+0.75, b+0.75<=a<b+1] for b in range(3)]

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

In [297]: funclist = list(itertools.chain([lambda x:-4*x+1, lambda x: 0, lambda x:4*x+1]*3))

In [298]: np.piecewise(a, condlist, funclist)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-298-41168765ae55> in <module>()
----> 1 np.piecewise(a, condlist, funclist)

/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/numpy/lib/function_base.pyc in piecewise(x, condlist, funclist, *args, **kw)
    688     if (n != n2):
    689         raise ValueError(
--> 690                 "function list and condition list must be the same")
    691     zerod = False
    692     # This is a hack to work around problems with NumPy's

ValueError: function list and condition list must be the same

目前,我对如何绘制这个函数感到相当困惑。我真的不理解错误消息,这进一步阻碍了我调试的努力。

最终,我希望将此函数绘制并导出为EPS文件,因此我也希望在这方面得到任何帮助。


1
尝试打破链接条件,例如a<b<c,这些与numpy数组不太兼容。https://dev59.com/TGkv5IYBdhLWcg3wwTZm - ev-br
就像@Zhenya所说的那样。例如,b <= a < b + 0.25必须写成(b <= a) & (a < b + 0.25) - Warren Weckesser
1个回答

12
总的来说,NumPy数组在你将代码写成数字的形式时非常擅长处理合理的事情。链式比较是少有的例外之一。你看到的错误本质上是这样的(由于piecewise内部和ipython错误格式化的缘故,稍微有些混淆)。
>>> a = np.array([1, 2, 3])
>>> 1.5 < a
array([False,  True,  True], dtype=bool)
>>> 
>>> 1.5 < a < 2.5
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
>>> 
>>> (1.5 < a) & (a < 2.5)
array([False,  True, False], dtype=bool)
>>> 

你也可以使用`np.logical_and`,但是位运算符`&`(而不是`and`)在这里完全可以正常工作。
就绘图而言,NumPy本身并不进行任何绘图操作。以下是一个使用matplotlib的示例:
>>> import numpy as np
>>> def piecew(x):
...   conds = [x < 0, (x > 0) & (x < 1), (x > 1) & (x < 2), x > 2]
...   funcs = [lambda x: x+1, lambda x: 1, 
...            lambda x: -x + 2., lambda x: (x-2)**2]
...   return np.piecewise(x, conds, funcs)
>>>
>>> import matplotlib.pyplot as plt
>>> xx = np.linspace(-0.5, 3.1, 100)
>>> plt.plot(xx, piecew(xx))
>>> plt.show() # or plt.savefig('foo.eps')

请注意,`piecewise` 是一个善变的东西。特别是,它需要其 `x` 参数是一个数组,并且如果不是(在 `numpy` 的术语中:`x` 需要是一个 `ndarray`,而不是一个 `array_like`),它甚至不会尝试进行转换。
>>> piecew(2.1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in piecew
  File "/home/br/.local/lib/python2.7/site-packages/numpy/lib/function_base.py", line 690, in piecewise
    "function list and condition list must be the same")
ValueError: function list and condition list must be the same
>>> 
>>> piecew(np.asarray([2.1]))
array([ 0.01])

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接