2012-04-30 68 views
4

我有一个渲染的图表需要3秒,然后可以从上图中添加事物的子图表添加到它。我想缓存主图表中的坐标轴,以便在绘制子图时可以检索并修改它。我怎么能通过这个错误?缓存带Memcache的Matplotlib(不会腌汁)

继承人的样本测试代码:

import pylibmc 
cache = pylibmc.Client(["127.0.0.1"], binary=True, behaviors={"tcp_nodelay": True, "ketama": True}) 
import matplotlib.pyplot as plt 


cache_name = 'test' 
fig = plt.figure(figsize=(20, 7)) 
ax = fig.add_axes([0, 0.15, 0.98, 0.85]) 
cache.set(cache_name, ax, 300) 

其中提供了以下错误:

cPickle.PicklingError: Can't pickle <type 'function'>: attribute lookup __builtin__.function failed 

有反正我能得到这个工作?

+1

数据结构是否需要3秒或matplotlib的实际绘图?之前已经有过关于这个的讨论,而且在制作matplotlib可序列化方面显然没有做过任何事情。 – jdi

+0

Matplotlib绘图。由于他们烛台的阴谋诡计,我正在绘制使用单个条形图的烛台图表。而且由于我不能通过列表工作(比较颜色,值,错误栏),所以我通过一个循环(大约400个项目)单独添加每个栏,这很可能导致它花费很长时间。示例脚本在这里:http://pastebin.com/6aD8YZfM。如果我能够缓存那些最终的小节,时间就不那么重要了。 – NoviceCoding

+0

那么在那个示例循环中,轴创建需要时间?你做了400次,产生一个需要3秒钟的轴的集合? – jdi

回答

3

有关于matplotlib数字的愿望能够被序列化的讨论。我还没有看到任何报道这个问题已被解决甚至被接受为目标。所以如果你试图通过线路发送给memcached,它显然会失败。我在搜索时发现的讨论表明,matplotlib的当前设计不容易满足这个目标,并且需要对内部进行重构。参考:http://old.nabble.com/matplotlib-figure-serialization-td28016714.html

你可以做什么,以大幅度减少执行时间,就是将数据重新组织到数据集中,并且只调用一次ax.bar()。然后可以将数据集序列化并以您想要的任何格式存储(例如,在memcached中)。

下面是一个代码示例,显示您的方法和将它们组合成数据集的方法之间的测试。您可以更轻松,如果你想在这里查看:https://gist.github.com/2597804

import matplotlib.pyplot as plt 
from random import randint 
from time import time 

DATA = [ 
    (i, randint(5,30), randint(5,30), randint(30,35), randint(1,5)) \ 
    for i in xrange(1, 401) 
] 

def mapValues(group): 
    ind, open_, close, high, low = group 
    if open_ > close: # if open is higher then close 
     height = open_ - close # heigth is drawn at bottom+height 
     bottom = close 
     yerr = (open_ - low, high - open_) 
     color = 'r' # plot as a white barr 
    else: 
     height = close - open_ # heigth is drawn at bottom+height 
     bottom = open_ 
     yerr = (close - low, high - close) 
     color = 'g' # plot as a black bar 

    return (ind, height, bottom, yerr, color) 

# 
# Test 1 
# 
def test1(): 
    fig = plt.figure() 
    ax = fig.add_subplot(111) 

    data = map(mapValues, DATA) 

    start = time() 

    for group in data: 

     ind, height, bottom, yerr, color = group 

     ax.bar(left=ind, height=height, bottom=bottom, yerr=zip(yerr), 
       color=color, ecolor='k', zorder=10, 
       error_kw={'barsabove': False, 'zorder': 0, 'capsize': 0}, 
       alpha=1) 

    return time()-start 

# 
# Test 2 
# 
def test2(): 
    fig = plt.figure() 
    ax = fig.add_subplot(111) 

    # plotData can be serialized 
    plotData = zip(*map(mapValues, DATA)) 

    ind, height, bottom, yerr, color = plotData 

    start = time() 

    ax.bar(left=ind, height=height, bottom=bottom, yerr=zip(*yerr), 
      color=color, ecolor='k', zorder=10, 
      error_kw={'barsabove': False, 'zorder': 0, 'capsize': 0}, 
      alpha=1) 

    return time()-start 


def doTest(fn): 
    end = fn() 
    print "%s - Sec: %0.3f, ms: %0d" % (fn.__name__, end, end*1000) 



if __name__ == "__main__": 
    doTest(test1) 
    doTest(test2) 

    # plt.show() 

结果:

python plot.py 
test1 - Sec: 1.592, ms: 1592 
test2 - Sec: 0.358, ms: 357 
+0

谢谢一堆。制图从5秒到1.7秒非常感谢!仍然希望长期使用matplotlib缓存机制! – NoviceCoding

-1

看着documentation,看起来fig.add_axes()将一个元组作为参数传递给列表。因此,它不会返回Axes对象(因为它没有被创建),所以ax被赋值给函数本身。

+1

这是不正确的。各种方法可以采取一个序列,无论是列表还是元组。无论哪种方式。 'add_axes()'返回一个'Axis'对象。问题在于OP试图通过线路将Axis实例发送到memcached,它希望能够序列化对象。 matplotlib对象不能被序列化。它基本上窒息了各轴的内部。看看'ax .__ dict__'的价值。你会看到它的其他matplotlib对象,包括图等巨大的参考。 – jdi

1

至于matplotlib 1.2的你应该可以咸菜和unpickle数字。

这是非常的“实验性”的特征,但如果你发现任何问题,请让我们知道MPL邮件列表或者通过github.com/matplotlib/matplotlib提出问题

HTH