Matplotlib_Venn,多个同比例Venn图

3
我目前有一个包含5个文氏图子图的图表。所有5个图都是2圆文氏图,并且每个图的元素总和不同。请参考这个图表
我想知道是否有可能将这6个子图都调整为相同的比例?例如,我的第一个文氏图应该被缩小到比第五个更小。
以下是代码。 非常感谢您的任何帮助。
from matplotlib_venn import venn2
from matplotlib import pyplot as plt
import numpy as np

figure, axes = plt.subplots(2, 3, figsize=(11.69,8.27))


BSL_20=(313,10,76)
BSL_40=(384,17,150)
BSL_100=(665,8,378)
BSL_100CC=(860,23,879)
BSL_200=(585,17,758)

v1=venn2(BSL_20, set_labels = ('150mm at 50%', '400mm at 25%'), ax=axes[0][0])
v2=venn2(BSL_40, set_labels = ('150mm at 50%', '400mm at 25%'), ax=axes[0][1])
v3=venn2(BSL_100, set_labels = ('150mm at 50%', '400mm at 25%'), ax=axes[0][2])
v4=venn2(BSL_100CC, set_labels = ('150mm at 50%', '400mm at 25%'), ax=axes[1][0])
v5=venn2(BSL_200, set_labels = ('150mm at 50%', '400mm at 25%'), ax=axes[1][1])
v6=venn2(BSL_200, set_labels = ('150mm at 50%', '400mm at 25%'), ax=axes[1][1])
axes[1,2].axis('off')

plt.show()
1个回答

4
plt.show()之前,尝试将以下内容添加到您的代码中:
from matplotlib.cbook import flatten

data = [BSL_20, BSL_40, BSL_100, BSL_100CC, BSL_200]
max_area = max(map(sum, data))

def set_venn_scale(ax, true_area, reference_area=max_area):
    s = np.sqrt(float(reference_area)/true_area)
    ax.set_xlim(-s, s)
    ax.set_ylim(-s, s)

for a, d in zip(flatten(axes), data):
    set_venn_scale(a, sum(d))

解释:

  • matplotlib_venn绘制的图形被缩放,使其总面积为1。该图形的中心位于点(0,0)附近,并且轴限制被配置为使图形紧密适合内部。
  • 这意味着,如果您只是为所有子图设置xlim(-1,1)ylim(-1,1),则会得到具有相同总面积的图形(假设所有子图以相同比例显示)。
  • 如果现在需要通过“缩小”其中一个图形来将其面积减少2,则可以通过简单地按sqrt(2)比例放大所有轴限制来实现。
  • 这就是上面的代码所做的:它首先确定具有最大实际总面积的圆集,然后仅按比例缩放其他图形的限制,即sqrt(max_area / required_area)

您还可以在Y轴上放松一些,并将代码和图表更紧密地打包如下:

from matplotlib_venn import venn2
from matplotlib.cbook import flatten
from matplotlib import pyplot as plt
import numpy as np

figure, axes = plt.subplots(2, 3, figsize=(11.69,5.5))

BSL_20=(313,10,76)
BSL_40=(384,17,150)
BSL_100=(665,8,378)
BSL_100CC=(860,23,879)
BSL_200=(585,17,758)

data = [BSL_20, BSL_40, BSL_100, BSL_100CC, BSL_200]
max_area = max(map(sum, data))

def set_venn_scale(vd, ax, true_area, reference_area=max_area):
    sx = np.sqrt(float(reference_area)/true_area)
    sy = max(vd.radii)*1.3
    ax.set_xlim(-sx, sx)
    ax.set_ylim(-sy, sy)

for a, d in zip(flatten(axes), data):
    vd = venn2(d, set_labels = ('150mm at 50%', '400mm at 25%'), ax=a)
    set_venn_scale(vd, a, sum(d))

axes[1,2].axis('off')
figure.tight_layout(pad=0.1)
plt.show()

请注意,tight_layout会在感觉空间不足时开始重新缩放您的子图,因此请检查结果(例如通过使用ax.set_axis_on()在您的子图周围添加轴,并确保所有子图具有相同的宽度)。


非常感谢您的帮助和详细解释,它非常有效! - Rachejen

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