如何从 matplotlib 图中提取数据
- 2025-03-25 08:47:00
- admin 原创
- 17
问题描述:
我有一个wxPython
程序,它可以读取不同的数据集,对数据执行各种类型的简单即时分析,并将数据集的各种组合绘制到matplotlib
画布上。我希望有机会将当前绘制的数据转储到文件中,以便以后进行更复杂的分析。
问题是:是否有任何方法matplotlib
可以访问当前绘制的数据matplotlib.Figure
?
解决方案 1:
Jakub 说得对,修改 Python 脚本可以直接从发送数据的源中写出数据,这也是我更喜欢的方式。但作为参考,如果你确实需要从图中获取数据,我认为这应该可以做到
gca().get_lines()[n].get_xydata()
或者,您可以分别获取 x 和 y 数据集:
line = gca().get_lines()[n]
xd = line.get_xdata()
yd = line.get_ydata()
解决方案 2:
可matplotlib.pyplot.gca
用于从 matplotlib 图中提取数据。这是一个简单的例子:
import matplotlib.pyplot as plt
plt.plot([1,2,3],[4,5,6])
ax = plt.gca()
line = ax.lines[0]
line.get_xydata()
运行此程序后,您将看到 2 个输出 - 图表和数据:
array([[1., 4.],
[2., 5.],
[3., 6.]])
您还可以分别获取 x 数据和 y 数据。运行时line.get_xdata()
,您将获得:
array([1, 2, 3])
运行时line.get_ydata()
,你将获得:
array([4, 5, 6])
注: gca
代表获取当前轴
解决方案 3:
总结一下,供以后参考:
如果使用plt.plot()
或plt.stem()
或绘图plt.step()
,您可以使用以下方法获取 Line2D 对象列表:
ax = plt.gca() # to get the axis
ax.get_lines()
对于plt.pie()
,plt.bar()
或者plt.barh()
您可以使用以下方法获取楔形或矩形对象的列表:
ax = plt.gca() # to get the axis
ax.patches()
然后,根据情况,您可以通过运行获取数据get_xdata()
(get_ydata()
请参阅Line2D)以获取更多信息。
或者,get_height()
有关条形图(参见矩形)的更多信息。
通常,对于所有基本绘图函数,你可以通过运行ax.get_children()来找到所需内容
返回子项的列表Artists
(基类包括图形的所有元素)。
解决方案 4:
我知道这是一个老问题,但我觉得有一个比这里提供的更好的解决方案,所以我决定写下这个答案。
您可以使用unittest.mock.patch
暂时替换该matplotlib.axes.Axes.plot
功能:
from unittest.mock import patch
def save_data(self, *args, **kwargs):
# save the data that was passed into the plot function
print(args)
with patch('matplotlib.axes.Axes.plot', new=save_data):
# some code that will eventually plot data
a_function_that_plots()
一旦退出with
阻止,Axes.plot
将恢复正常行为。
解决方案 5:
它是 Python,因此您可以直接修改源脚本,以便在绘制数据之前将其转储
解决方案 6:
正如@mobiuscreek在回答中指出的那样,从轴中提取数据的方式取决于用于绘图的函数:例如,ax.get_lines()
对于通过创建的绘图有效ax.plot()
,但如果使用创建了线条,则会给出一个空数组matplotlib.collections.LineCollection
。 (当图形由第三方代码创建时,可能会出现更大的问题。)
然后,一般的方法是ax.get_children()
根据需要使用和解析它。例如,请参阅此答案。
解决方案 7:
建议仅从“发送到绘图的源”获取数据的原因是因为所有 matplotlib 方法都需要frombuffer canvas tostring_rgb()/buffer_rgba()
喧闹,并且之后可能会导致 UB,因为 matplotlib 在不同平台(matplotlib 后端)上的行为不同
它也非常慢
我刚刚编写了我自己的 in-numpy 绘图仪,它以矢量化的方式绘制所有内容,没有单个关键路径循环,并且比 matplotlib hoopla 快至少 100 倍。
https://github.com/bedbad/justpyplot
import numpy as np
import cv2
import time
import justpyplot as jplt
xs, ys = [], []
while(cv2.waitKey(1) != 27):
xt = time.perf_counter() - t0
yx = np.sin(xt)
xs.append(xt)
ys.append(yx)
frame = np.full((500,470,3), (255,255,255), dtype=np.uint8)
vals = np.array(ys)
plotted_in_array = jplt.just_plot(frame, vals,title="sin() from Clock")
cv2.imshow('np array plot', plotted_in_array)