2016-03-21 133 views
0

如何将统计图形(图,轴,图表等)添加到在python-igraph中实现的现有图形中?我对matplotlib特别感兴趣,因为我有这个库的经验。如何将matplotlib与igraph一起使用?

在我的情况下,igraph正在用于不同的布局选项。我的当前网络的x维度部分受到约束,而y由布局更改。我想在图的底部添加一个条形图,以列出与网络节点的x坐标相关的值的频率。

(我不使用SciPy的/ IPython中/熊猫库,尚未反正)

回答

2

这不是一个完整的答案,但它是太长发布的评论,所以我张贴它作为而是一个答案。随意扩展/编辑它。

前段时间(当然,超过五年前),我已经尝试过将python-igraphmatplotlib合并在一起,一般的结论是将两者结合是可能的,但是以相当复杂的方式。

首先,只有当您将开罗用作matplotlib的图形后端时,组合才有效,因为python-igraph使用开罗作为图形绘制后端(并且不支持任何其他绘图后端)。

接下来,关键技巧是,你可以提取Matplotlib人物莫名其妙的开罗表面,然后通过这个表面的igraph的plot()功能作为描绘对象 - 在这种情况下,IGRAPH不会创建一个单独的数字,但只是开始绘制给定的表面。然而,当我正在试验这个时候,Matplotlib中没有公开的API从图中提取开罗曲面,所以我不得不求助于未公开的Matplotlib属性和函数,因此整个事情非常脆弱并且依赖于它严重依赖于我已经使用过的特定版本的Matplotlib - 但它很有效。

整个过程总结在this thread上的igraph-help邮件列表中。在线程中,我提供了以下Python脚本作为一个验证的概念,我在这里复制它的完整性的缘故:

from matplotlib.artist import Artist 
from igraph import BoundingBox, Graph, palettes 

class GraphArtist(Artist): 
    """Matplotlib artist class that draws igraph graphs. 

    Only Cairo-based backends are supported. 
    """ 

    def __init__(self, graph, bbox, palette=None, *args, **kwds): 
     """Constructs a graph artist that draws the given graph within 
     the given bounding box. 

     `graph` must be an instance of `igraph.Graph`. 
     `bbox` must either be an instance of `igraph.drawing.BoundingBox` 
     or a 4-tuple (`left`, `top`, `width`, `height`). The tuple 
     will be passed on to the constructor of `BoundingBox`. 
     `palette` is an igraph palette that is used to transform 
     numeric color IDs to RGB values. If `None`, a default grayscale 
     palette is used from igraph. 

     All the remaining positional and keyword arguments are passed 
     on intact to `igraph.Graph.__plot__`. 
     """ 
     Artist.__init__(self) 

     if not isinstance(graph, Graph): 
      raise TypeError("expected igraph.Graph, got %r" % type(graph)) 

     self.graph = graph 
     self.palette = palette or palettes["gray"] 
     self.bbox = BoundingBox(bbox) 
     self.args = args 
     self.kwds = kwds 

    def draw(self, renderer): 
     from matplotlib.backends.backend_cairo import RendererCairo 
     if not isinstance(renderer, RendererCairo): 
      raise TypeError("graph plotting is supported only on Cairo backends") 
     self.graph.__plot__(renderer.gc.ctx, self.bbox, self.palette, *self.args, **self.kwds) 


def test(): 
    import math 

    # Make Matplotlib use a Cairo backend 
    import matplotlib 
    matplotlib.use("cairo.pdf") 
    import matplotlib.pyplot as pyplot 

    # Create the figure 
    fig = pyplot.figure() 

    # Create a basic plot 
    axes = fig.add_subplot(111) 
    xs = range(200) 
    ys = [math.sin(x/10.) for x in xs] 
    axes.plot(xs, ys) 

    # Draw the graph over the plot 
    # Two points to note here: 
    # 1) we add the graph to the axes, not to the figure. This is because 
    # the axes are always drawn on top of everything in a matplotlib 
    # figure, and we want the graph to be on top of the axes. 
    # 2) we set the z-order of the graph to infinity to ensure that it is 
    # drawn above all the curves drawn by the axes object itself. 
    graph = Graph.GRG(100, 0.2) 
    graph_artist = GraphArtist(graph, (10, 10, 150, 150), layout="kk") 
    graph_artist.set_zorder(float('inf')) 
    axes.artists.append(graph_artist) 

    # Save the figure 
    fig.savefig("test.pdf") 

    print "Plot saved to test.pdf" 

if __name__ == "__main__": 
    test() 

一句警告:我没有测试上面的代码现在我无法测试它,因为我的机器上现在没有Matplotlib。它使用五年前与当时的Matplotlib版本(0.99.3)工作。如果没有重大修改,它可能无法工作,但它显示了总体思路,并希望它不会太复杂以适应。

如果您设法使它适合您,请随时编辑我的帖子。

+0

谢谢,示例代码除了需要将'matplotlib.use(“cairo.pdf”)'交换到'matplotlib.use(“cairo”)'之外。将继续在此工作,并更新/接受,当我了解更多。 – Annan

相关问题