You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何用Python绘制可按大小体现数量的重叠圆(类欧拉图)

如何用Python绘制可按大小体现数量的重叠圆(类欧拉图)

首先我先梳理下你的核心需求,确保我完全get到了重点:
你需要用Python实现欧拉图风格的可视化,替代matplotlib-venn(最多支持3个圆、默认标签是数量而非自定义名称)和R的eulerr(不熟悉R),具体要求包括:

  • 支持超过3个集合的展示
  • 可以自定义每个圆的标题/标签(比如直接用"poodles"、"dogs"而不是数字)
  • 圆的面积、重叠区域对应集合的元素数量或逻辑包含关系
  • 能根据像All x are ySome 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每个区域就能看到对应的数量,还能缩放、保存图片。

三、处理复杂逻辑语句的小技巧

对于你给出的复杂逻辑语句(比如包含多个AllSome的组合),可以分两步处理:

  1. 解析逻辑关系:把语句转换成集合规则,比如:
    • All x are y → x是y的子集,x∩y = x的大小
    • Some z are non-y → z的大小 > z∩y的大小
    • All non-x are y → y是全集,y的大小等于所有集合的并集
  2. 计算集合大小:给每个集合分配一个基础大小,再根据逻辑调整交集大小
  3. 生成可视化:把计算好的大小传给上面的库,就能得到对应的欧拉图

对于矛盾的逻辑(比如All dogs are animals, All animals are poodles),你可以在解析时检测到矛盾,然后生成一个反例图(比如画一个不在poodles里的dog圆)来直观展示。

四、自定义样式优化

两个库都支持自定义样式,比如:

  • 调整填充颜色、透明度
  • 修改边框颜色、粗细
  • 自定义标签的字体大小、颜色
  • 添加标题、图例位置调整

你可以根据自己的理想图效果,调整这些参数,让可视化更贴合需求。


备注:内容来源于stack exchange,提问作者Kristina Zerbinopoulos

火山引擎 最新活动