【问题标题】:Plot Discrete Distribution using np.linspace()使用 np.linspace() 绘制离散分布
【发布时间】:2017-12-06 21:11:36
【问题描述】:

我正在尝试使用 matplotlib 绘制一个简单的离散分布:

  • 如果 -1
  • 如果 0
  • 如果 1

如何从x = np.linspace(-1, 2)开始?

到目前为止我尝试的是:

def mapDiscProb(x):
    if np.any(x < 0):
        return 0.3 + x * 0
    elif np.any(x >= 1):
        return 0.2 + x * 0
    else:
        return 0.5 + x * 0

x = np.linspace(-1, 2)
y = mapDiscProb(x4)

ax.plot(x, y, clip_on = False)

结果只是从 -1 到 2 的 0.3 整行,好像 elif 和 else 没有被执行。

我的预期输出是三个断开的水平线,这是离散 pmf 的标准。

【问题讨论】:

  • 到目前为止你尝试过什么?你有什么问题?您只是想绘制 PDF(如直方图)还是其他?你的标题是“映射”,但你的问题是“情节”。
  • 您是否尝试在linespace 中的所有号码上独立使用此功能?否则只有第一个if 会触发是有道理的,因为数组中的数字总是小于 0
  • @djk47463 是的,这就是我的想法:将linspace 中的所有数字归入正确的类别并绘制图表。
  • 你可以设置y = [mapDiscProb(z) for z in x]
  • 您必须在边界处屏蔽值

标签: python numpy matplotlib


【解决方案1】:

你可以使用

numpy.piecewise

numpy.piecewise 允许根据某些条件定义函数。这里有三个条件[x&lt;0, x&gt;=1, (x&gt;=0) &amp; (x&lt;1)],你可以为每个条件定义一个函数。

import matplotlib.pyplot as plt
import numpy as np

l1 = lambda x: 0.3 + x * 0
l2 = lambda x: 0.2 + x * 0
l3 = lambda x: 0.5 + x * 0

mapDiscProb=lambda x: np.piecewise(x, [x<0, x>=1, (x>=0) & (x<1)],[l1,l2,l3])

x = np.linspace(-1, 2)
y = mapDiscProb(x)

fig, ax = plt.subplots()
ax.plot(x, y, clip_on = False)

plt.show()

numpy.vectorize

numpy.vectorize 向量化一个函数,该函数打算用标量调用,这样就可以对数组中的每个元素进行评估。这允许if/else 语句按预期使用。

import matplotlib.pyplot as plt
import numpy as np

def mapDiscProb(x):
    if x < 0:
        return 0.3
    elif x >= 1:
        return 0.2
    else:
        return 0.5

x = np.linspace(-1, 2)
y = np.vectorize(mapDiscProb)(x)

fig, ax = plt.subplots()
ax.plot(x, y, clip_on = False)

plt.show()

numpy.select

(此想法归功于 PaulH)numpy.select 可以根据条件从不同的数组中选择选择值。对于分段常量函数,这是一个简单的工具,因为它不需要构建任何额外的函数(单线)。

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(-1, 2)
y = np.select([x<0, x<1, x>1], [0.3, 0.5, 0.2])

fig, ax = plt.subplots()
ax.plot(x, y, clip_on = False)

plt.show()

所有情况下的输出:

没有垂直线

如果您不希望出现任何垂直线,则可以根据条件绘制尽可能多的图。

import matplotlib.pyplot as plt
import numpy as np

l1 = lambda x: 0.3 + x * 0
l2 = lambda x: 0.2 + x * 0
l3 = lambda x: 0.5 + x * 0

x = np.linspace(-1, 2)
func = [l1,l2,l3]
cond = [x<0, x>=1, (x>=0) & (x<1)]

fig, ax = plt.subplots()
for f,c in zip(func,cond):
    xi = x[c]
    ax.plot(xi, f(xi), color="C0")

plt.show()

或者,使用numpy.select,您可以修改x 数组以确保包含值[0,1],它们位于条件之间的边缘。选择明确排除这些值的条件,[x&lt;0, (x&gt;0) &amp; (x&lt;1), x&gt;1](注意缺少任何等号)将允许将这些值设置为 nan。 Nan值未显示,因此出现间隙。

import matplotlib.pyplot as plt
import numpy as np

x = np.sort(np.append(np.linspace(-1, 2),[0,1]))
y = np.select([x<0, (x>0) & (x<1), x>1], [0.3, 0.5, 0.2], np.nan)

fig, ax = plt.subplots()
ax.plot(x, y)

plt.show()

【讨论】:

  • 谢谢,但有没有办法消除图中“几乎垂直”的线条?
  • 您不想要任何垂直线还是希望它们是垂直的?
  • 我不想要那些垂直线。
  • 更新了答案。
  • 您可以使用numpy.select 将边界处的值设置为numpy.nan ...例如y = numpy.select([x&lt;0, x&lt;1, x&gt;1], [0.3, 0.5, 0.2], numpy.nan)
【解决方案2】:

如果你只是想为那个例子做,这应该可以工作

import numpy as np
from matplotlib import pyplot as plt
x=np.linspace(-1,2)
plt.plot(x[x < 0], 0.3 + x[x < 0]*0, color='blue')
plt.plot(x[(x >= 0) & (x <= 1)], 0.5 + x[(x>=0) & (x<=1)]*0, color='blue')
plt.plot(x[x > 1],0.2 + x[x > 1]*0, color='blue')
plt.show()

当涉及到离散函数时,我的方法是屏蔽。

【讨论】:

  • 像前面的答案一样,您基本上将 3 个不同的均匀分布绘制为 1 个离散分布。我认为这是一个聪明的选择,你用更少的代码来做同样的事情。我只是想知道离散分布,似乎没有办法先构建一个 y=f(x) 并使用单个 plot(x, y) 绘制的函数,是这样吗?
  • 只是为了捍卫我的答案:其中的最后一个选项使用的代码比这少得多。 ;-)
猜你喜欢
  • 1970-01-01
  • 2019-03-03
  • 2012-06-27
  • 2018-08-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-05
  • 1970-01-01
相关资源
最近更新 更多