Python绘制含全局包围区域的韦恩图:移除默认标签与修正区域大小问题
Python绘制含全局包围区域的韦恩图:移除默认标签与修正区域大小问题
看起来你已经离目标很近了!咱们来搞定剩下的两个小问题——去掉默认的A/B/C标签,还有让图里的区域大小和你给定的真实数值完全匹配上,同时保持你想要的“全局圈包裹两个子集”的效果。
一、先解决默认标签的问题
venn3会自动给三个集合加上A、B、C的默认标识,咱们只需要找到这些标签然后把它们隐藏就行。用v.get_label_by_id('A')这类方法拿到对应标签,再调用set_visible(False)就能把它们藏起来,简单直接。
二、修正区域大小:搞对subsets的数值逻辑
你之前的集合大小设置逻辑有点偏差,导致区域显示不对。咱们先理清楚三个集合的对应关系:
- 集合A:全局包围圈(包含所有元素,包括只属于全局的部分、两个子集的独立项、以及它们的交集)
- 集合B:第一个子集(SDSS-FIRST, $i-t_f > 2.5$,总数量13552)
- 集合C:第二个子集(SDSS-FIRST-Quaia-VLASS, $G-t > 2.5$,总数量7887)
根据你原来的venn2数据,咱们可以算出各个独立区域的真实大小:
- 只属于B的部分:$13552 - 7747 = 5805$
- 只属于C的部分:$7887 - 7747 = 140$
- B和C的交集:$7747$
- 只属于全局A的部分:这里我用
only_global = 2000作为示例,你可以替换成你数据中“只属于全局、不在两个子集里”的真实数量,如果没有这部分数据,也可以调整这个数值来让全局圈的视觉大小符合你的需求。
下面是修正后的完整代码:
from collections import Counter import matplotlib.pyplot as plt from matplotlib_venn import venn3 # ---------------------- 计算正确的区域大小 ---------------------- # 原始数据 total_B = 13552 # 集合B的总数量 total_C = 7887 # 集合C的总数量 intersection_BC = 7747# B和C的交集数量 only_global = 2000 # 只属于全局包围圈的数量(替换成你的真实数据) # 计算各独立区域的大小 only_B = total_B - intersection_BC only_C = total_C - intersection_BC # 构建venn3需要的subsets字典 sets = Counter() sets["100"] = only_global # 只属于全局A sets["110"] = only_B # 属于A和B,不属于C sets["101"] = only_C # 属于A和C,不属于B sets["111"] = intersection_BC# 属于A、B、C三者 # ---------------------- 绘制韦恩图 ---------------------- plt.figure(figsize=(8, 6)) v = venn3(subsets=sets) # ---------------------- 自定义标签 ---------------------- v.get_label_by_id('100').set_text(f"只属于全局集合\nN={only_global}") v.get_label_by_id('110').set_text("SDSS-FIRST,\n$i-t_f > 2.5$\nN=13552") v.get_label_by_id('101').set_text("SDSS-FIRST-\nQuaia-VLASS,\n$G-t > 2.5$\nN=7887") v.get_label_by_id('111').set_text("$i-t_f > 2.5$,\n$G-t > 2.5$\nN=7747") # ---------------------- 隐藏默认的A/B/C标签 ---------------------- for label_id in ['A', 'B', 'C']: label = v.get_label_by_id(label_id) if label: label.set_visible(False) # ---------------------- 自定义样式:仅边框着色 ---------------------- # 全局圈(100)用黑色,B区域(110)红色,C区域(101)蓝色,交集(111)绿色 for subset, color in zip(['100', '110', '101', '111'], ['black', 'red', 'blue', 'green']): patch = v.get_patch_by_id(subset) if patch: patch.set_edgecolor(color) patch.set_linewidth(4) patch.set_facecolor('none') # ---------------------- 自定义标签颜色 ---------------------- v.get_label_by_id('100').set_color('black') v.get_label_by_id('110').set_color('red') v.get_label_by_id('101').set_color('blue') v.get_label_by_id('111').set_color('green') plt.show()
关键说明
- 区域大小匹配:现在subsets里的数值都是真实的元素数量,
venn3会自动根据这些数值调整各个区域的面积大小,保证视觉上和真实数量成比例。 - 默认标签移除:通过遍历A/B/C三个默认标签,设置
set_visible(False)彻底隐藏它们,不会在图上显示。 - 全局圈的逻辑:把全局包围圈对应到venn3的第一个集合(A),这样它的区域会自然包裹住B和C两个子集,完美实现你想要的“大圈包小圈”的效果。
如果你的“只属于全局”的部分没有数据,只是想画一个包围框,也可以把only_global设为0,但这样全局圈的边框会和两个子集的外边界重合,你可以适当调大这个数值(比如1000、2000)来让全局圈的边框明显包裹住两个子集,数值越大,全局圈的范围就越宽。
备注:内容来源于stack exchange,提问作者NeStack
相关产品推荐
相关产品推荐

