Seaborn 非常适合根据对每个面的类别进行编码的分类变量来创建面图。但是,这假设您的类别是相互排斥的。是否可以基于一组指标变量创建 Seaborn FacetGrid
(或类似的)?
作为一个具体示例,考虑比较感染一种或多种病毒的患者,并按病毒绘制感兴趣的属性。一个病人可能携带不止一种病毒,因此不可能创建一个 virus
列来创建网格。但是,您可以创建一组指示变量(每个病毒一个)来标记每个患者的病毒。似乎没有办法将一组指示变量传递给任何 Seaborn 函数来执行此操作。
我无法想象我是第一个遇到这种情况的人,所以我希望有关于如何做到这一点的建议,而无需在 Matplotlib 中手动编码。
最佳答案
我不知道如何用 FacetGrid 做到这一点,可能是因为这不是对数据进行分面,因为数据记录可能在图中出现多次或只出现一次。一组位域的标准技巧之一是将它们作为二进制读取,这样您就可以看到位的每个组合。这是明确的,但会变得困惑:
import pandas as pd
import seaborn as sns
from numpy.random import random, randint
from numpy import concatenate
import matplotlib.pyplot as plt
# Dummy data
vdata = pd.DataFrame(concatenate((randint(2, size=(32,4)), random(size=(32,2))), axis=1))
vdata.columns=['Species','v1','v2','v3','x','y']
binary_v = vdata.v1 + vdata.v2*2 + vdata.v3*4
# Making a binary number out of the "virusX?" fields
pd.concat((vdata, binary_v), axis=1)
vdata = pd.concat((vdata, binary_v), axis=1)
vdata.columns=['Species','v1','v2','v3','x','y','binary_v']
# Plotting group membership by row
#g = sns.FacetGrid(vdata, col="Species", row='binary_v')
#g.map(plt.scatter, "x", "y")
#g.add_legend()
#plt.savefig('multiple_facet_binary_row') # Unreadably big.
h = sns.FacetGrid(vdata, col="Species", hue="binary_v")
h.map(plt.scatter, "x","y")
h.add_legend()
plt.savefig('multiple_facet_binary_hue')
如果您有太多指标来处理组合爆炸,明确地使新子集起作用:
# Nope, need to pull out subsets:
bdata = vdata[vdata.v1 + vdata.v2 + vdata.v3 ==0.]
assert(len(bdata) > 0) # ... catch...
bdata['Virus'] = pd.Series(['none']*len(bdata), index=bdata.index)
for i in ['v1','v2','v3']:
on = vdata[vdata[i]==1.]
on['Virus'] = pd.Series([i]*len(on), index=on.index)
bdata = bdata.append(on)
j = sns.FacetGrid(bdata, col='Species', row='Virus')
j.map(plt.scatter, 'x', 'y')
j.add_legend()
j.savefig('multiple_facet_refish')
关于python - 使用指标变量而不是单列创建多面 matplotlib/seaborn 图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42125011/