Python: 维恩图:如何显示图表内容?
Python: Venn diagram: how to show the diagram contents?
我有下面的工作代码。
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()
如何在这3个圆圈中显示每个集合的内容?颜色 alpha 为 0.6。圆圈必须更大才能容纳所有符号。
我不确定是否有一种简单的方法可以自动为任何可能的集合组合执行此操作。如果您准备好在您的特定示例中进行一些手动调整,请从类似的开始:
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')
return matplotlib Text
对象这样的方法,您可以根据自己的喜好自由配置它们(例如,您可以通过调用 set_fontsize(8)
, 等等).
这是一个自动化整个过程的例子。它创建一个临时字典,其中包含 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()
感谢自动化,@Vinci!我想知道您(或其他人)是否编写了一个重新排列内容的版本,以便元素以随机方式而不是一长串的方式留在气泡中? ...奖金轨道:如果元素不适合,重新确定气泡的尺寸? ;)
我有下面的工作代码。
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()
如何在这3个圆圈中显示每个集合的内容?颜色 alpha 为 0.6。圆圈必须更大才能容纳所有符号。
我不确定是否有一种简单的方法可以自动为任何可能的集合组合执行此操作。如果您准备好在您的特定示例中进行一些手动调整,请从类似的开始:
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')
return matplotlib Text
对象这样的方法,您可以根据自己的喜好自由配置它们(例如,您可以通过调用 set_fontsize(8)
, 等等).
这是一个自动化整个过程的例子。它创建一个临时字典,其中包含 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()
感谢自动化,@Vinci!我想知道您(或其他人)是否编写了一个重新排列内容的版本,以便元素以随机方式而不是一长串的方式留在气泡中? ...奖金轨道:如果元素不适合,重新确定气泡的尺寸? ;)