【问题标题】:Conditional Plotting with Numpy and Pyplot使用 Numpy 和 Pyplot 进行条件绘图
【发布时间】:2016-07-21 11:14:59
【问题描述】:

我正在尝试绘制一个有条件定义的函数。具体来说: U(x) = (2**delta)/((Dd)**delta)*(D/2 - (x-x0))**delta ,对于 abs(x-x0) 小于 D/2 和 0否则。

但我的问题是我想将 x, x0 作为 numpy 数组,因为这是我在其余实际代码中使用它们的方式。

我已经设置了以下示例:

import numpy as np
import matplotlib.pyplot as plt
AD = 0.2
D = 0.4
delta = 8

def Parabolic(x, delta, D, AD):
    x0 = np.round(x)
    tempx = np.abs(x-x0)
    tempD = D/2*np.ones(len(x))
    if tempx<tempD:
        return ((2**delta)/(D-AD)**delta)*(D/2 - (x-x0))**delta
    else:
        return 0

figure = plt.figure(figsize=(10,8), dpi=72)  
xmin = -1.0
xmax = 1.0
X = np.linspace(xmin,xmax,1000)
plt.plot(X, Parabolic(X, delta=8, D=0.4, AD=0.2))

显然这个例子不起作用,因为tempx&lt;tempD 行引发了列表的真值不明确的错误。

我搜索了 numpy 的文档,找到了函数 np.less(tempx, tempD)。但是如果我用np.less(tempx, tempD) 替换tempx &lt; tempD 它仍然不起作用,因为我再次要求整个列表的真值。我知道问题不在于 numpy,而在于我无法理解如何使用 numpy 提供的逻辑函数。

如果这在另一篇文章中以某种方式回答,我很抱歉,我在这个论坛中搜索但除了curve() 方法之外找不到其他东西。但是我想保留我的 numpy.array 格式以在我的实际代码中使用。我敢打赌,答案一定很简单,我就是想不出来。

【问题讨论】:

标签: python numpy plot comparison conditional


【解决方案1】:

抛物线必须是一个ufunc,所以你不能在你的代码中放置python测试。

一个简单的解决方法是:

def Parabolic(x, delta, D, AD):
    x0 = np.round(x)
    tempx = np.abs(x-x0)
    tempD = D/2*np.ones(len(x))
    u=(((2**delta)/(D-AD)**delta)*(D/2 - (x-x0))**delta)
    u[tempx>=tempD]=0
    return u  

或避免不必要的计算:

def Parabolic2(x, delta, D, AD):
    x0 = np.round(x)
    tempx = np.abs(x-x0)
    tempD = D/2*np.ones(len(x))
    u= zeros_like(x)
    valid=tempx<tempD
    u[valid]=(((2**delta)/(D-AD)**delta)*(D/2 - (x-x0)[valid])**delta)
    return u

第二个稍微快一点:

In [141]: %timeit Parabolic(x,8,.4,.2)
1000 loops, best of 3: 310 µs per loop

In [142]: %timeit Parabolic2(x,8,.4,.2)
1000 loops, best of 3: 218 µs per loop

【讨论】:

  • 这也是一个很好的解决方法,而且代码非常简单。然而,这确实意味着我必须计算所有值的函数,无论大小。这在普通代码中会花费很多时间。我打算将第一个答案用于u 函数的非常高和非常小的值,主要是为了避免计算。
  • 我认为第二个版本不会起作用,因为u[tempx&lt;tempD] 的长度会小于等式右侧返回的数组。
  • 我尝试运行代码,确实因为你说的原因它没有完成。
【解决方案2】:

试试这个使用 numpy 逻辑数组的方法:

import numpy as np
import matplotlib.pyplot as plt
AD = 0.2
D = 0.4
delta = 8

def Parabolic(x, delta, D, AD):
    rtn_arr = np.zeros(len(x))
    x0 = np.round(x)
    tempx = np.abs(x-x0)
    tempD = D/2*np.ones(len(x))
    lgc_arr = tempx<tempD
    x_cut = x[lgc_arr]
    x0_cut = x0[lgc_arr]
    rtn_arr[lgc_arr] = ((2**delta)/(D-AD)**delta)*(D/2 - (x_cut-x0_cut))**delta
    return rtn_arr

figure = plt.figure(figsize=(10,8), dpi=72)
xmin = -1.0
xmax = 1.0
X = np.linspace(xmin,xmax,1000)
plt.plot(X, Parabolic(X, delta=8, D=0.4, AD=0.2))

【讨论】:

  • 嗯,这正是我想要的。我设法使用 python 列表和附加解决了我的问题,但当然不是那么好。你的就是我要找的。我不知道可以使用x_cut = x[lgc_array] 来仅获取与true 对应的元素!最后一件事:你能解释一下lgc_arr = tempx&lt;tempD 是如何工作的吗? numpy 数组是否会自动更改关系/比较运算符的工作方式并自动返回一个 numpy 数组?
  • tempx&lt;tempD 也在您的代码中返回一个数组。但是您尝试在 Python if 上下文中使用该结果。在需要标量布尔值的上下文中使用任何 numby 布尔数组会产生 ValueError
  • @GeorgeDatseris 正如你所说。 numpy 数组重新定义了条件运算符(可以为任何自定义类 docs.python.org/2/library/stdtypes.html 完成),以便在 numpy 数组上使用 &gt;, &lt; 等返回 numpy 数组。那么tempx&lt;tempD就是一个布尔值数组,可以和x[lgc_array]做数组切片。
猜你喜欢
  • 2018-01-22
  • 1970-01-01
  • 2018-11-22
  • 2018-08-04
  • 2020-05-15
  • 1970-01-01
  • 1970-01-01
  • 2016-01-15
  • 2012-12-12
相关资源
最近更新 更多