konstantint / matplotlib-venn

Area-weighted venn-diagrams for Python/matplotlib
MIT License
495 stars 67 forks source link

Error for 0 value of venn3 #60

Closed JamesWZM closed 3 years ago

JamesWZM commented 3 years ago
v = venn3(subsets=(1,0,1,10,69,3,20)) # this one is what I want
v = venn3(subsets=(1,1,0,10,69,3,20)) # this is what venn3 actually build

as you can see, they just build same figure which is not what I want

JamesWZM commented 3 years ago

This is the first line plot show: image The second one: image

JamesWZM commented 3 years ago

I've checked the source code, it might be caused by the accuracy of float number computing. But I need this figure, maybe I should draw it in hand?

konstantint commented 3 years ago

There are 6 degrees of freedom in the positioning of circles and 7 degrees of freedom in the subsets vector - consequently, there is mathematically no way for a 3-way circle-based Venn diagram to represent every possible subset configuration accurately.

Things usually get bad when one of the subsets is much larger than the others- this forces the layout algorithm to come up with graphs like yours, where the dominating intersections pull circles together in a configuration, where some of the areas are not even present.

A common remedy in this situation is to "regularize" the subset areas vector by artificially increasing every region's area by a certain fixed amount. This usually normalizes the diagram somewhat (by pushing it more towards an unweighed version). Try this:

from matplotlib_venn import venn3_unweighted
subsets=(1,1,0,10,69,3,20)
v = venn3_unweighted(subsets=subsets, subset_areas=tuple(s+3 for s in subsets))

You still won't see much difference between the two configurations you compare (because, objectively, they are numerically close), but at least this way one of the areas is not disappearing.