用Python制作拱形关系信息图

4 投票
3 回答
887 浏览
提问于 2025-04-15 15:41

这是一个非常具体的信息图表挑战,基本问题是如何使用matplotlib、cairo或其他Python库在单词之间建立弧线。

给定以下数据结构。

me, you, 7 |
me, apple, 9 |
apple, you, 1 |
bike, me, 5

名字会水平显示,关系最多的名字会比其他的更大,然后在名字之间会有加权的弧线。比如,一个权重为10的弧线会比一个权重为5的弧线粗两倍。

灵感来源于:相似多样性。 http://similardiversity.net/

让挑战开始吧!

3 个回答

0

我其实看不出有什么难点或者挑战。你只需要一个可以画文字和半圆的图形库,这在很多地方都能做到。根本不需要用到贝塞尔曲线。比如,你可以简单地创建一个SVG文件(这样你甚至不需要任何库,就可以把它很好地嵌入到网页中,并用一些JavaScript让它变得互动)。

实际的绘制过程很简单:圆心就在两个词之间的中间,半径就是它们之间距离的一半。然后你可以调整线条的粗细来表示其他的数量。

4

matplotlib 这个库不太适合你现在的需求,因为它不是一个通用的图形库。你需要的是像 Cairo 这样的库,或者更简单一点,你可以用任何图形用户界面工具包的图形功能,比如 PyQt。还有一个不错的选择是 PyGame,它也有很好的绘图功能。

如果你想看个例子,可以去看看这个 Cairo 示例 页面,里面有个第一个示例 - arc。你只需要写上文字,然后用 arc 代码来画出任意宽度和颜色的弧线。

1

有几个库可以满足你的需求,其中至少有一个是依赖于Matplotlib的。我推荐使用Networkx(网址:www.networkx.lanl.gov)来构建你的图形结构,然后你可以用它来调用相关的Matplotlib方法进行绘图。Networkx和Matplotlib的配合非常好。

import networkx as NX
import matplotlib.pyplot as PLT
Gh = NX.Graph()
Gh.add_edge("You", "Bike", weight=1.0)
Gh.add_edge("Bike", "Apple", weight=0.9)
Gh.add_edge("Me", "Bike", weight=1.1)
all_nodes = Gh.nodes()
# to scale node size with degree:
scaled_node_size = lambda(node) : NX.degree(Gh, node) * 700
position = NX.spring_layout(Gh)    # just choose a layout scheme
NX.draw_networkx_nodes(Gh, position, node_size=map(scaled_node_size, all_nodes))
NX.draw_network_edges(Gh, position, Gh.edges(), width=1.0, alpha=1.0, edge_color="red")
# now for the Matplotlib part:
PLT.axis("off")
PLT.show()

正如你所看到的,你可以通过给“权重”参数加一个系数来调整边的大小,这和我为节点缩放所做的方式是一样的。

我还推荐pygraphviz(显然是使用graphviz作为后端)。它和Networkx非常相似(都是同一个主要开发者)。

撰写回答