Alex Rivera | Logout

Proportional venn diagram for more than 3 sets

Asked 2012-05-29T18:10:40.767
11

I have a collection of documents in MongoDB where each has one or more categories in a list. Using map reduce, I can get the details of how many documents have each unique combination of categories:

['cat1']               = 523
['cat2']               = 231
['cat3']               = 102
['cat4']               = 72
['cat1','cat2']        = 710
['cat1','cat3']        = 891
['cat1','cat3','cat4'] = 621 ...

where the totals are for the number of documents that exact combination of categories.

I'm looking for a sensible way to present this data, and I think a venn diagram with proportional areas would be a good idea. Using the above example, the area cat1 would be 523+710+891+621, the area of the overlap between cat1 and cat3 would be 891+621, the area of overlap between cat1, cat3, cat4 would be 621 etc.

Does anyone have any tips for how I might go about implementing this? I'd preferably like to do it in Python (+Numpy/MatPlotLib) or MatLab.

Edit
Report

1 Answer

6

I believe ninjagecko is correct and this cannot generally be represented as a diagram of intersections, unless you don't mind the diagram being in n dimensions. However, it can be represented in 2D if you have a diagram for each category showing all its intersections - and this itself can be a single diagram. So this may be a more appropriate way to represent your data. I've produced a stacked barchart to illustrate:

enter image description here

The code:

cats = ['cat1','cat2','cat3','cat4']
data = {('cat1',): 523, ('cat2',): 231, ('cat3',): 102, ('cat4',): 72, ('cat1','cat2'): 710,('cat1','cat3'): 891,('cat1','cat3','cat4') : 621}

import matplotlib.pyplot as plt
import numpy as np
from random import random

colors = dict([(k,(random(),random(),random())) for k in data.keys()])
print colors
for i, cat in enumerate(sorted(cats)):
    y = 0
    for key, val in data.items():
        if cat in key:
            plt.bar(i, val, bottom=y, color=colors[key])
            plt.text(i,y,' '.join(key))
            y += val
plt.xticks(np.arange(len(cats))+0.4, sorted(cats))
plt.show()
answered 2012-05-29T21:49:32.123

Your Answer