2016-03-21 107 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

相關問題