在igraph绘图中添加标题和图例

7
在 Python 的 igraph 中,你能为一个图表添加图例和标题吗?就我所见,手册和教程中都没有提到。不过在 R 中是可以实现的。
1个回答

10
R提供了一个相当先进的绘图系统,R接口直接使用它,这就是为什么你可以在R中轻松创建图表标题和图例。Python默认不提供任何绘图功能,因此igraph使用Cairo库来绘制图形。然而,Cairo只是一个通用的矢量图形库。这就是为什么在Python中无法获得相同的高级绘图能力。
igraph的plot函数在后台创建了一个Plot对象,将正在绘制的图形添加到绘图本身中,为其创建适当的Cairo表面,然后开始在Cairo表面上绘制图形。如果您只使用图形作为参数简单地调用plot,所有这些都会在幕后发生。但是,您可以手动创建一个Plot对象,然后在绘制它之前向其中添加标签,例如:
>>> plot = Plot("plot.png", bbox=(600, 600), background="white")

在这一点上,您有一个名为plot的变量,它是igraph.drawing.Plot的实例。该图由一个Cairo图像表面支持,宽度为600像素,高度为600像素,并最终保存到名为plot.png的文件中(也可以直接在Plot构造函数的第一个参数中提供Cairo表面)。调用plot.redraw()会绘制图形,但不会立即保存。调用plot.save()会绘制图形(如果尚未绘制),然后将其保存到指定的文件名中。
然后,您可以使用图进行两件事情:
  1. Add an arbitrary object to the plot that has a __draw__ method. Graph objects have such a method so you can add a graph to the plot as follows:

    >>> g = Graph.GRG(100, 0.2)
    >>> plot.add(g, bbox=(20, 20, 580, 580))
    
  2. Grab its surface property to access the Cairo surface on which the drawing is done, construct a Cairo drawing context with this surface, and then draw on the plot directly with Cairo using the drawing context.

第二种选项是我们将如何向图表添加标签。幸运的是,igraph在igraph.drawing.text包中提供了一个名为TextDrawer的类,可以帮助我们解决换行和对齐问题。我们只需要创建一个TextDrawer,然后调用它的draw_at方法,在给定位置添加标签即可:
>>> import cairo
>>> context = cairo.Context(plot.surface)
>>> text_drawer = TextDrawer(context, text="Test label", halign=TextDrawer.LEFT)
>>> text_drawer.draw_at(x=100, y=100)

`TextDrawer`将使用Cairo上下文的当前字体绘制标签,因此您需要使用Cairo上下文的`set_font_face`、`set_font_size`和相关方法来调整用于绘制的字体。
将所有内容放在一起,示例如下:
from igraph import Graph, Plot
from igraph.drawing.text import TextDrawer
import cairo

# Construct the plot
plot = Plot("plot.png", bbox=(600, 650), background="white")

# Create the graph and add it to the plot
g = Graph.GRG(100, 0.2)
plot.add(g, bbox=(20, 70, 580, 630))

# Make the plot draw itself on the Cairo surface
plot.redraw()

# Grab the surface, construct a drawing context and a TextDrawer
ctx = cairo.Context(plot.surface)
ctx.set_font_size(36)
drawer = TextDrawer(ctx, "Test title", halign=TextDrawer.CENTER)
drawer.draw_at(0, 40, width=600)

# Save the plot
plot.save()

示例将在图形中添加标题。构建图例更为复杂,但希望您可以基于此思路进一步进行。图例的标签可通过重复调用TextDrawerdrawdraw_at方法来构造(当然,在每次调用之间需要调整TextDrawertext属性)。您可以使用标准的Cairo调用在图例周围绘制框。您还可以使用igraph.drawing.shapes中的节点绘制类来绘制节点形状,类似于igraph在绘制图形时使用的形状。

谢谢。我觉得这比许多人想要的要稍微复杂一些。是否可能将此功能添加到igraph中,以便用户可以隐藏细节? - Simd
2
我会研究添加这个功能的可能性。问题是,igraph并不意味着成为一个全面的绘图包,我不想重复造轮子,所以我试图尽可能地减少包含在igraph中的绘图代码量。我可能会通过传递单个关键字参数给plot来添加绘图标题的可能性,但我认为除非有人发送补丁,否则不会实现绘图图例。 - Tamás
谢谢。也许按照你所说的将图表导出并找到另一个绘制它们的软件包会更合适。然而,我不确定那会是什么。 - Simd
4
在进行科学出版物的绘图时,我通常会先用igraph制作初步图形,然后将其导出为SVG文件,并在Inkscape中进一步编辑SVG文件,以添加图例、标题或其他内容。另一个选择是Gephi。你可以将igraph图形导出为GraphML格式,然后将其加载到Gephi中。 - Tamás

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接