gnuplot 与 Matplotlib

93 投票
8 回答
68233 浏览
提问于 2025-04-15 11:50

我开始了一个项目,目的是用Tomcat的日志来绘图,使用的是gnuplot-py,特别是想把特定的请求和内存分配、垃圾回收联系起来。大家对gnuplot-py和Matplotlib在Python绘图方面有什么看法?有没有更好的绘图库是我没听说过的?

我考虑的主要问题有:

  • 虽然gnuplot有很多文档,但gnuplot-py的文档就少得多。Matplotlib的社区文档怎么样?
  • 有没有gnuplot能做但gnuplot-py做不了的事情?
  • Matplotlib对Python的支持更好吗?
  • 这两个库有没有严重的bug或者让人烦恼的问题?
  • 现在gnuplot能处理十万的数据点,我打算把这个规模扩大到几百万。这样会有问题吗?Matplotlib处理这个的能力怎么样?
  • 使用的方便程度,gnuplot和Matplotlib的响应时间如何?
  • 把现有的gnuplot-py代码移植到Matplotlib上会有多难?

你会怎么处理这个任务呢?

8 个回答

26

matplotlib 的文档写得很好,而且它的稳定性也不错。它生成的图表非常漂亮,绝对可以达到“出版级别”。因为文档清晰,还有很多在线示例代码,所以学习和使用起来很简单。我觉得你在把 gnuplot 的代码转换成它的时候不会遇到太大困难。毕竟,很多科学家都在用 matplotlib 来绘制数据和准备报告,所以它包含了所有需要的功能。

matplotlib 的一个明显优势是,它可以和 Python 的图形用户界面(GUI)结合使用,比如 wxPythonPyQt,这样你就可以创建带有漂亮图表的应用程序。

50

Matplotlib = 使用简单,Gnuplot = (稍微更好一点的)性能


我知道这篇文章已经很旧了,也有人回答过,但我路过的时候想说说我的看法。我的结论是:如果你的数据集不大,建议使用Matplotlib。它更简单,效果也更好。不过,如果你真的需要更好的性能,可以试试Gnuplot。我还加了一些代码,供你在自己电脑上测试,看看是否真的有区别(这不是一个真正的性能测试,但可以给你一个初步的印象)。

下面的图表显示了绘制一个随机散点图所需的时间(以秒为单位):

  • 绘制随机散点图
  • 将图表保存为png文件

Gnuplot 与 Matplotlib 的对比

配置:

  • gnuplot: 5.2.2
  • gnuplot-py: 1.8
  • matplotlib: 2.1.2

我记得在旧电脑上运行旧版本的库时,性能差距更大(对于一个大散点图,差不多有30秒的差距)。

而且,正如评论中提到的,你可以用Gnuplot得到相同质量的图表。但你需要花更多的时间和精力去实现这一点。


如果你想在自己的电脑上试试,这里有生成图表的代码

# -*- coding: utf-8 -*-

from timeit import default_timer as timer
import matplotlib.pyplot as plt
import Gnuplot, Gnuplot.funcutils
import numpy as np
import sys
import os

def mPlotAndSave(x, y):
    plt.scatter(x, y)
    plt.savefig('mtmp.png')
    plt.clf()

def gPlotAndSave(data, g):
    g("set output 'gtmp.png'")
    g.plot(data)
    g("clear")

def cleanup():
    try:
        os.remove('gtmp.png')
    except OSError:
        pass
    try:
        os.remove('mtmp.png')
    except OSError:
        pass

begin = 2
end = 500000
step = 10000
numberOfPoints = range(begin, end, step)
n = len(numberOfPoints)
gnuplotTime = []
matplotlibTime = []
progressBarWidth = 30

# Init Gnuplot
g = Gnuplot.Gnuplot()
g("set terminal png size 640,480")

# Init matplotlib to avoid a peak in the beginning
plt.clf()

for idx, val in enumerate(numberOfPoints):
    # Print a nice progress bar (crucial)
    sys.stdout.write('\r')
    progress = (idx+1)*progressBarWidth/n
    bar = "▕" + "▇"*progress + "▁"*(progressBarWidth-progress) + "▏" + str(idx) + "/" + str(n-1)
    sys.stdout.write(bar)
    sys.stdout.flush()

    # Generate random data
    x = np.random.randint(sys.maxint, size=val)  
    y = np.random.randint(sys.maxint, size=val)
    gdata = zip(x,y)

    # Generate string call to a matplotlib plot and save, call it and save execution time
    start = timer()
    mPlotAndSave(x, y)
    end = timer()
    matplotlibTime.append(end - start)

    # Generate string call to a gnuplot plot and save, call it and save execution time
    start = timer()
    gPlotAndSave(gdata, g)
    end = timer()
    gnuplotTime.append(end - start)

    # Clean up the files
    cleanup()

del g
sys.stdout.write('\n')
plt.plot(numberOfPoints, gnuplotTime, label="gnuplot")
plt.plot(numberOfPoints, matplotlibTime, label="matplotlib")
plt.legend(loc='upper right')
plt.xlabel('Number of points in the scatter graph')
plt.ylabel('Execution time (s)')
plt.savefig('execution.png')
plt.show()
54
  • 你可以自己查看 matplotlib的文档,我觉得内容非常全面。
  • 我对gnuplot-py的了解很少,所以不能确定它是否能做所有gnuplot能做的事情。
  • Matplotlib是专门为Python编写和设计的,所以它和Python的用法非常契合。
  • Matplotlib是一个成熟的项目,甚至NASA也在用它做一些事情。
  • 我在Matplotlib中绘制了数千万个点,效果依然很美观,响应也很快。
  • 除了面向对象的使用方式,Matplotlib还有一个叫pylab的接口,让绘图变得像在MATLAB中一样简单——也就是说,非常简单。
  • 至于从gnuplot-py迁移到matplotlib,我就不太清楚了。

撰写回答