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绘图
Linux服务器没有GUI的情况下使用matplotlib绘图