Matplotlib_Venn, несколько диаграмм Венна одного масштаба

В настоящее время у меня есть фигура с 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 ответ

Решение

Попробуйте добавить это в свой код, прежде чем 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() и убедитесь, что все участки имеют одинаковую ширину).

Другие вопросы по тегам