Python 的 Matplotlib 绘图顺序错误

Posted

技术标签:

【中文标题】Python 的 Matplotlib 绘图顺序错误【英文标题】:Python's Matplotlib plotting in wrong order 【发布时间】:2021-11-27 03:03:00 【问题描述】:

基本上我有两个数组,一个包含 x 轴的值,第二个包含 y 轴的值。问题是,当我这样做时

plt.semilogy(out_samp,error_mc)

我明白了

这没有任何意义。这是因为 plot 函数绘制 x 数组中遇到的所有内容,而不关心它是否按升序排序。如何对这两个数组进行排序,以便 x 数组按递增值排序,y 轴按相同方式排序,以便点相同但绘图是连接的,以免造成混乱?

提前谢谢你!

【问题讨论】:

输入数据是 Python 列表还是 numpy 向量? 它们是列表。对不起,我应该这么说的。 您可以使用散点图(在您的图表上具有未链接的点),而不是绘制一条线,作为第一步 【参考方案1】:

对列表进行排序的另一种方法是使用 NumPy 数组并使用 np.sort() 进行排序。使用数组的优势在于在计算 y=f(x) 之类的函数时进行矢量化操作。以下是绘制正态分布的示例:

不使用排序数据

mu, sigma = 0, 0.1
x = np.random.normal(mu, sigma, 200)
f = 1/(sigma * np.sqrt(2 * np.pi)) *np.exp( - (x - mu)**2 / (2 * sigma**2) )
plt.plot(x,f, '-bo', ms = 2)

输出 1

使用 np.sort() 这允许在计算正态分布时直接使用排序数组 x

mu, sigma = 0, 0.1
x = np.sort(np.random.normal(mu, sigma, 200)) 
# or use x = np.random.normal(mu, sigma, 200).sort()
f = 1/(sigma * np.sqrt(2 * np.pi)) *np.exp( - (x - mu)**2 / (2 * sigma**2) )
plt.plot(x,f, '-bo', ms = 2)

或者,如果您已经有未排序的 x 和 y 数据,您可以使用 numpy.argsort 对它们进行后验排序

mu, sigma = 0, 0.1
x = np.random.normal(mu, sigma, 200)
f = 1/(sigma * np.sqrt(2 * np.pi)) *np.exp( - (x - mu)**2 / (2 * sigma**2) )
plt.plot(np.sort(x), f[np.argsort(x)], '-bo', ms = 2)

请注意,上面的代码使用了两次sort():首先使用np.sort(x),然后使用f[np.argsort(x)]sort() 调用总数可以减少到一个:

# once you have your x and f...
indices = np.argsort(x)
plt.plot(x[indices], f[indices], '-bo', ms = 2)

在这两种情况下,输出都是

输出 2

【讨论】:

您仍然可以只使用一次sort(x) 来提高性能。 @ThomasKühn:我在答案中添加了它作为替代 我编辑了答案以使其更清晰。如果您不同意,您可以恢复更改。 @ImportanceOfBeingErnest:一切正常。 ;) 可接受所有更改 @Sheldore 我认为您仍在使用两次排序:首先,当您使用np.sort(x) 时,然后当您使用f[np.argsort(x)] 时。我会改为indices = np.argsort(x),然后通过以下方式进行绘图:plt.plot(x[indices], f[indices])【参考方案2】:

在绘图前按 x 轴的值排序。这是一个 MWE。

import itertools

x = [3, 5, 6, 1, 2]
y = [6, 7, 8, 9, 10]

lists = sorted(itertools.izip(*[x, y]))
new_x, new_y = list(itertools.izip(*lists))

# import operator
# new_x = map(operator.itemgetter(0), lists)        # [1, 2, 3, 5, 6]
# new_y = map(operator.itemgetter(1), lists)        # [9, 10, 6, 7, 8]

# Plot
import matplotlib.pylab as plt
plt.plot(new_x, new_y)
plt.show()

对于小数据,zip(其他回答者提到的)就足够了。

new_x, new_y = zip(*sorted(zip(x, y)))

结果,

【讨论】:

我得到一个“ValueError:解包的值太多”。试图弄清楚这意味着什么。向量仅包含 50 个值。 (错误出现在 sorted(...) 行)。 @akinn,我刚刚取消了我的答案,包括一个例子。 好的,现在可以了,谢谢。不过,我想知道,这样更有效率吗?我的意思是使用 itertools 和运算符。 other 提供的其他解决方案似乎也有效。 @akinn, zip 需要立即获取所有项目。 izip 只推进底层迭代器。 @akinn,详细说明请参考itertools — Functions creating iterators for efficient looping。【参考方案3】:

您可以将数组转换为 numpy 数组,然后在第一个数组上使用 argsort,获取数组并使用 argsort 数组对两个数组进行排序。

【讨论】:

我绘制了一个散点图,但它不容易解释。本质上,我的 x 向量是迭代次数,y 是误差。【参考方案4】:

我认为您需要对一个数组进行排序,而另一个数组也应该根据第一个数组进行排序。我从其他一些堆栈溢出问题中得到了这个解决方案。很可能这应该是您的解决方案。

out_samp,error_mc=zip(*sorted(zip(out_samp,error_mc)))

现在绘制这两个值,你会得到一个正确的图表。

【讨论】:

【参考方案5】:

zip、sort 和 unzip 这两个数据列表更容易。

例子:

xs = [...]
ys = [...]

xs, ys = zip(*sorted(zip(xs, ys)))

plot(xs, ys)

在此处查看 zip 文档:https://docs.python.org/3.5/library/functions.html#zip

【讨论】:

你应该是最佳答案【参考方案6】:

就这样做

list=zip(*sorted(zip(*(x,y))))
plt.plot(*list)

sorted 函数将根据第一个参数,即 x 值进行排序

【讨论】:

但是,在 Python 3 中,据我所见,它返回一个元组。我赞成你的回答。但是,您的列表变量实际上是一个元组。 (顺便说一下,使用 list 作为变量是一个非常糟糕的主意,因为 list 是一个内置的数据结构,而 list()从技术上初始化一个列表。)

以上是关于Python 的 Matplotlib 绘图顺序错误的主要内容,如果未能解决你的问题,请参考以下文章

AttributeError: ‘Rectangle‘ object has no property ‘normed‘ 解决方法 matplotlib绘图

用 matplotlib 绘图 - 试图保存我的比例顺序

Linux服务器没有GUI的情况下使用matplotlib绘图

python数据可视化之matplotlib.pyplot绘图时图片显示不全的解决方法(图文并茂版!!!)

Python绘图matplotlib

python绘图之matplotlib