如何显示维恩图的图表内容

3
我有下面的工作代码。
from matplotlib import pyplot as plt
import numpy as np
from matplotlib_venn import venn3, venn3_circles
Gastric_tumor_promoters = set(['DPEP1', 'CDC42BPA', 'GNG4', 'RAPGEFL1', 'MYH7B', 'SLC13A3', 'PHACTR3', 'SMPX', 'NELL2', 'PNMAL1', 'KRT23', 'PCP4', 'LOX', 'CDC42BPA'])

Ovarian_tumor_promoters = set(['ABLIM1','CDC42BPA','VSNL1','LOX','PCP4','SLC13A3'])

Gastric_tumor_suppressors = set(['PLCB4', 'VSNL1', 'TOX3', 'VAV3'])
#Ovarian_tumor_suppressors = set(['VAV3', 'FREM2', 'MYH7B', 'RAPGEFL1', 'SMPX', 'TOX3'])
venn3([Gastric_tumor_promoters,Ovarian_tumor_promoters, Gastric_tumor_suppressors], ('GCPromoters', 'OCPromoters', 'GCSuppressors'))

venn3([Gastric_tumor_promoters,Ovarian_tumor_promoters, Gastric_tumor_suppressors], ('GCPromoters', 'OCPromoters', 'GCSuppressors'))
plt.show()

如何在这三个圆中显示每个集合的内容?颜色透明度为0.6。圆必须更大以容纳所有符号。
3个回答

9

我不确定是否有一种简单的方式可以自动为任何可能的集合组合进行此操作。如果您准备在您的特定示例中进行一些手动调整,请从以下内容开始:

A = set(['DPEP1', 'CDC42BPA', 'GNG4', 'RAPGEFL1', 'MYH7B', 'SLC13A3', 'PHACTR3', 'SMPX', 'NELL2', 'PNMAL1', 'KRT23', 'PCP4', 'LOX', 'CDC42BPA'])
B = set(['ABLIM1','CDC42BPA','VSNL1','LOX','PCP4','SLC13A3'])
C = set(['PLCB4', 'VSNL1', 'TOX3', 'VAV3'])

v = venn3([A,B,C], ('GCPromoters', 'OCPromoters', 'GCSuppressors'))

v.get_label_by_id('100').set_text('\n'.join(A-B-C))
v.get_label_by_id('110').set_text('\n'.join(A&B-C))
v.get_label_by_id('011').set_text('\n'.join(B&C-A))
v.get_label_by_id('001').set_text('\n'.join(C-A-B))
v.get_label_by_id('010').set_text('')
plt.annotate(',\n'.join(B-A-C), xy=v.get_label_by_id('010').get_position() +
             np.array([0, 0.2]), xytext=(-20,40), ha='center',
             textcoords='offset points', 
             bbox=dict(boxstyle='round,pad=0.5', fc='gray', alpha=0.1),
             arrowprops=dict(arrowstyle='->',              
                             connectionstyle='arc',color='gray'))

请注意,像v.get_label_by_id('001')这样的方法会返回matplotlib Text对象,您可以自由配置它们以满足您的需求(例如,您可以通过调用set_fontsize(8)来更改字体大小等)。

1
这是一个自动化整个过程的示例。它创建一个临时字典,其中包含venn需要的id作为键以及此id的所有参与集合的交集。
如果您不想对标签进行排序,请在倒数第二行中删除sorted()调用。
import math
from matplotlib import pyplot as plt
from matplotlib_venn import venn2, venn3
import numpy as np

# Convert number to indices into binary
# e.g. 5 -> '101' > [2, 0]
def bits2indices(b):
    l = []
    if b == 0:
        return l
    for i in reversed(range(0, int(math.log(b, 2)) + 1)):
        if b & (1 << i):
            l.append(i)
    return l

# Make dictionary containing venn id's and set intersections
# e.g. d = {'100': {'c', 'b', 'a'}, '010': {'c', 'd', 'e'}, ... }
def set2dict(s):
    d = {}
    for i in range(1, 2**len(s)):
        # Make venn id strings
        key = bin(i)[2:].zfill(len(s))
        key = key[::-1]
        ind = bits2indices(i)
        # Get the participating sets for this id
        participating_sets = [s[x] for x in ind] 
        # Get the intersections of those sets
        inter = set.intersection(*participating_sets)
        d[key] = inter
    return d

# Define some sets
a = set(['a', 'b', 'c']) 
b = set(['c', 'd', 'e'])
c = set(['e', 'f', 'a'])
s = [a, b, c]

# Create dictionary from sets
d = set2dict(s)

# Plot it
h = venn3(s, ('A', 'B', 'C'))
for k, v in d.items():
    l = h.get_label_by_id(k)
    if l:
        l.set_text('\n'.join(sorted(v)))
plt.show()

对不起,我刚刚发现上面的代码没有去除重复的标签,因此是错误的。由venn显示的元素数量和标签数量不同。这里是一个新版本,可以从其他交叉点中删除错误的重复项。我想还有一种更聪明、更功能性的方法来做到这一点,而不是两次迭代所有交叉点...
import math, itertools
from matplotlib import pyplot as plt
from matplotlib_venn import venn2, venn3
import numpy as np

# Generate list index for itertools combinations
def gen_index(n):
    x = -1
    while True:       
        while True:
            x = x + 1
            if bin(x).count('1') == n:
                break
        yield x

# Generate all combinations of intersections
def make_intersections(sets):
    l = [None] * 2**len(sets)
    for i in range(1, len(sets) + 1):
        ind = gen_index(i)
        for subset in itertools.combinations(sets, i):
            inter = set.intersection(*subset)
            l[next(ind)] = inter
    return l

# Get weird reversed binary string id for venn
def number2venn_id(x, n_fill):
    id = bin(x)[2:].zfill(n_fill)
    id = id[::-1]
    return id

# Iterate over all combinations and remove duplicates from intersections with
# more sets
def sets2dict(sets):
    l = make_intersections(sets)
    d = {}
    for i in range(1, len(l)):
        d[number2venn_id(i, len(sets))] = l[i]
        for j in range(1, len(l)):
            if bin(j).count('1') < bin(i).count('1'):
                l[j] = l[j] - l[i]
                d[number2venn_id(j, len(sets))] = l[j] - l[i]
    return d

# Define some sets
a = set(['a', 'b', 'c', 'f']) 
b = set(['c', 'd', 'e'])
c = set(['e', 'f', 'a'])
sets = [a, b, c]

d = sets2dict(sets)

# Plot it
h = venn3(sets, ('A', 'B', 'C'))
for k, v in d.items():
   l = h.get_label_by_id(k)
   if l:
       l.set_fontsize(12)
       l.set_text('\n'.join(sorted(v)))

# Original for comparison
f = plt.figure(2)
venn3(sets, ('A', 'B', 'C'))  
plt.show()

0
感谢自动化,@Vinci!我想知道您(或其他人)是否编写了一个版本,可以以随机方式重新排列元素,以便它们保持在气泡内,而不是一长串的列表?...额外加分项:如果元素不适合,是否可以重新调整气泡的尺寸?;)

v850_instruction_sets


1
据我所知,您可以使用https://github.com/paulbrodersen/matplotlib_venn_wordcloud。 - teoML

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