如何用Python绘制可按大小体现数量的重叠圆(类欧拉图)
首先我先梳理下你的核心需求,确保我完全get到了重点:
你需要用Python实现欧拉图风格的可视化,替代matplotlib-venn(最多支持3个圆、默认标签是数量而非自定义名称)和R的eulerr(不熟悉R),具体要求包括:
- 支持超过3个集合的展示
- 可以自定义每个圆的标题/标签(比如直接用"poodles"、"dogs"而不是数字)
- 圆的面积、重叠区域对应集合的元素数量或逻辑包含关系
- 能根据像
All x are y、Some z are non-y这类逻辑语句,自动生成对应的重叠/嵌套圆效果
接下来给你推荐几个实用的Python解决方案,附上手示例:
一、用eulerr库生成专业欧拉图
这是最贴合你需求的Python库——它专门做欧拉图,支持最多5个集合,能自动根据集合大小调整圆的面积和重叠区域,还能自定义标签,完美解决matplotlib-venn的局限。
安装
pip install eulerr
示例1:嵌套集合(对应All poodles are dogs, All dogs are animals)
这个例子里,poodles是dogs的子集,dogs是animals的子集,我们直接定义各集合和交集的大小,就能生成嵌套的圆:
from eulerr import Euler import matplotlib.pyplot as plt # 定义集合与交集的大小(子集的交集等于自身大小) set_sizes = { "poodles": 15, "dogs": 40, "animals": 70, "poodles&dogs": 15, "poodles&animals": 15, "dogs&animals": 40, "poodles&dogs&animals": 15 } # 生成欧拉图,自定义标签 fig, ax = Euler(set_sizes).plot( labels=["Poodles", "Dogs", "Animals"], legend=True, fill_opacity=0.5, # 调整透明度 edgecolor="black" # 圆的边框颜色 ) ax.set_title("Nested Euler Diagram") plt.show()
运行后会生成一个大的Animals圆,里面包含Dogs圆,Dogs圆里又包含Poodles圆,每个圆的面积和你定义的大小对应。
示例2:带部分重叠的集合(对应All x are y, All non-x are y, Some z are non-y)
这个逻辑里,y是全集(x和非x都属于y),z部分属于y、部分不属于,我们可以这样定义:
set_sizes = { "x": 25, "y": 100, # y是全集,设为最大 "z": 35, "x&y": 25, # x完全在y里 "x&z": 0, # 逻辑里没提到x和z的交集,设为0 "y&z": 15, # z有15个元素在y里,剩下20个在外面 "x&y&z": 0 } fig, ax = Euler(set_sizes).plot( labels=["x", "y", "z"], legend=True, fill_opacity=0.5 ) plt.show()
结果会是y的大圆包裹x,z的圆一部分和y重叠,一部分在y外,完全符合你的逻辑要求。
二、用Plotly实现交互式欧拉图
如果你需要交互式可视化(比如鼠标hover查看重叠区域的具体数量),可以用Plotly。它支持最多4个集合,虽然是韦恩图,但如果某个交集不存在,设置大小为0就能呈现欧拉图的效果。
安装
pip install plotly
示例代码
import plotly.graph_objects as go # 定义集合与交集大小 set_sizes = { "A": 40, "B": 60, "C": 30, "A∩B": 20, "A∩C": 0, "B∩C": 10, "A∩B∩C": 0 } # 生成交互式图 fig = go.Figure(data=[go.Venn( sets=["A", "B", "C"], # 计算每个区域的大小(韦恩图的格式要求) values=[ set_sizes["A"] - set_sizes["A∩B"] - set_sizes["A∩C"] + set_sizes["A∩B∩C"], set_sizes["B"] - set_sizes["A∩B"] - set_sizes["B∩C"] + set_sizes["A∩B∩C"], set_sizes["A∩B"] - set_sizes["A∩B∩C"], set_sizes["C"] - set_sizes["A∩C"] - set_sizes["B∩C"] + set_sizes["A∩B∩C"], set_sizes["A∩C"] - set_sizes["A∩B∩C"], set_sizes["B∩C"] - set_sizes["A∩B∩C"], set_sizes["A∩B∩C"] ], # 自定义标签样式 label=dict(font=dict(size=16, color="white"), bgcolor="#1f77b4"), textfont=dict(size=14) )]) fig.update_layout(title_text="Interactive Euler-like Diagram") fig.show()
运行后会在浏览器打开一个交互式图,hover每个区域就能看到对应的数量,还能缩放、保存图片。
三、处理复杂逻辑语句的小技巧
对于你给出的复杂逻辑语句(比如包含多个All、Some的组合),可以分两步处理:
- 解析逻辑关系:把语句转换成集合规则,比如:
All x are y→ x是y的子集,x∩y = x的大小Some z are non-y→ z的大小 > z∩y的大小All non-x are y→ y是全集,y的大小等于所有集合的并集
- 计算集合大小:给每个集合分配一个基础大小,再根据逻辑调整交集大小
- 生成可视化:把计算好的大小传给上面的库,就能得到对应的欧拉图
对于矛盾的逻辑(比如All dogs are animals, All animals are poodles),你可以在解析时检测到矛盾,然后生成一个反例图(比如画一个不在poodles里的dog圆)来直观展示。
四、自定义样式优化
两个库都支持自定义样式,比如:
- 调整填充颜色、透明度
- 修改边框颜色、粗细
- 自定义标签的字体大小、颜色
- 添加标题、图例位置调整
你可以根据自己的理想图效果,调整这些参数,让可视化更贴合需求。
备注:内容来源于stack exchange,提问作者Kristina Zerbinopoulos




