How to add labels inside circles of the Venn diagram in python?

1.7k Views Asked by At

I am using the matplotlib_venn.venn2 function to plot the Venn diagram in a single figure. My code:

from matplotlib_venn import venn2
from matplotlib import pyplot as plt
total = 150
# depict venn diagram
venn2(subsets = (61, 48, 13), set_labels = ('Advanced Mathematics', 'linear Algebra'),
      set_colors=('#00909e', '#f67280'),
    subset_label_formatter=lambda x: f"{(x/total):1.0%}"
)
plt.show()

Result:

enter image description here

However, I wanted to add the topics of each subject inside the circle, for example inside Advanced Mathematics the following topics should be written (Calculus and analysis, Logic, Number theory) and Linear Algebra topics (Mathematical operations, Matrix inverses and determinants) should be written inside Linear Algebra.

2

There are 2 best solutions below

8
On

you can set custom text to labels

labels = ['100', '010']
custom_text = ["Advanced Mathematics",'linear Algebra' ]
for label_id, text in zip(labels, custom_text):
    v.get_label_by_id(label_id).set_text(text)
1
On

The venn2 function used for creating two-circle Venn diagrams returns an object of type VennDiagram. This object provides access to the labels via the get_label_by_id() function. The IDs for two-circle diagrams are '10' (left), '01' (right), and '11' (intersection) according to the source code of class VennDiagram. 1

So by assigning the result of the venn2 call to a variable diagram will help adjust the subset labels:

subsets = (61, 48, 13)  # `subsets` is used in the next code box
diagram = venn2(
    subsets = subsets, 
    set_labels = ('Advanced Mathematics', 'linear Algebra'),
    set_colors=('#00909e', '#f67280')
)

# display the label IDs themselves as subgroup labels
for id in ('10','11','01'):
    diagram.get_label_by_id(id).set_text(id)

plt.show()

As discussed, there is no limitation to labels except the logic of formatting labels that comes with matplotlib.text. In other words, it's almost impossible to get the layout you described in the updated question. Here is what I tried to get as close as possible [replace the for loop with it]:

diagram.get_label_by_id('10').set_text(f"""
Calculus and analysis

Logic

{subsets[0]/total:1.0%}


Number theory

""")
diagram.get_label_by_id('01').set_text(f"""
Mathematical
operations

{subsets[1]/total:1.0%}

Matrix inverses
and determinants
""")
diagram.get_label_by_id('11').set_text(f'{subsets[2]/total:1.0%}')

But what I got from it …

enter image description here

… is not quite impressive. To do this, you really have to count rows (and don't forget the blank rows) to align the percentages vertically. From an aesthetic point of view, I would say that we are not using the right tool.


1 As shown in the answer Nikolay Tsvetanov, the first IDs for three-circle Venn diagrams ('100', '010', '110') work either.