Seaborn catplot 和 PairGrid 的组合

6

我正在处理泰坦尼克号数据集,并试图生成一个数值变量与分类变量之间的成对图。我可以使用Seaborn的catplot绘制一个数值变量与一个分类变量的图:

import seaborn as sns

sns.catplot(data=train, x='Fare', y='Sex')

然而,如果我尝试使用PairGrid将数值变量与分类变量绘制图表:
x_vars = ['Fare']
y_vars = ['Sex']

g = sns.PairGrid(train, x_vars=x_vars, y_vars=y_vars)
g.map(sns.catplot)

这会出现一个错误:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-75-c284a7cfd727> in <module>
      9 #g.map_diag(lambda x, **kwargs: sns.catplot(x, x, **kwargs), jitter=True, kind="bar")
     10 #g.map(sns.scatterplot, y_jitter=1)#, hue=train["Survived"])
---> 11 g.map(sns.catplot)#, hue=train["Survived"])

~/MLProject/book1/lib/python3.8/site-packages/seaborn/axisgrid.py in map(self, func, **kwargs)
   1363         row_indices, col_indices = np.indices(self.axes.shape)
   1364         indices = zip(row_indices.flat, col_indices.flat)
-> 1365         self._map_bivariate(func, indices, **kwargs)
   1366         return self
   1367 

~/MLProject/book1/lib/python3.8/site-packages/seaborn/axisgrid.py in _map_bivariate(self, func, indices, **kwargs)
   1504             y_var = self.y_vars[i]
   1505             ax = self.axes[i, j]
-> 1506             self._plot_bivariate(x_var, y_var, ax, func, kw_color, **kws)
   1507         self._add_axis_labels()
   1508 

~/MLProject/book1/lib/python3.8/site-packages/seaborn/axisgrid.py in _plot_bivariate(self, x_var, y_var, ax, func, kw_color, **kwargs)
   1534             color = self.palette[k] if kw_color is None else kw_color
   1535 
-> 1536             func(x, y, label=label_k, color=color, **kwargs)
   1537 
   1538         self._clean_axis(ax)

~/MLProject/book1/lib/python3.8/site-packages/seaborn/categorical.py in catplot(x, y, hue, data, row, col, col_wrap, estimator, ci, n_boot, units, seed, order, hue_order, row_order, col_order, kind, height, aspect, orient, color, palette, legend, legend_out, sharex, sharey, margin_titles, facet_kws, **kwargs)
   3760 
   3761     # Initialize the facets
-> 3762     g = FacetGrid(**facet_kws)
   3763 
   3764     # Draw the plot onto the facets

~/MLProject/book1/lib/python3.8/site-packages/seaborn/axisgrid.py in __init__(self, data, row, col, hue, col_wrap, sharex, sharey, height, aspect, palette, row_order, col_order, hue_order, hue_kws, dropna, legend_out, despine, margin_titles, xlim, ylim, subplot_kws, gridspec_kws, size)
    268         # Make a boolean mask that is True anywhere there is an NA
    269         # value in one of the faceting variables, but only if dropna is True
--> 270         none_na = np.zeros(len(data), np.bool)
    271         if dropna:
    272             row_na = none_na if row is None else data[row].isnull()

TypeError: object of type 'NoneType' has no len()

如果我将 g.map(sns.catplot) 替换为 g.map(sns.scatterplot),它会成功地绘制图表而没有错误。

如何将 catplotPairGrid 结合使用?


7
seaborn.catplot 会创建自己的图形并将 FacetGrid 插入其中。因此,您在这里尝试创建一个 PairGrid,并为每个网格成员创建一个新图和一个新网格。但这样做行不通。所以答案很简单:您无法将 catplotPairGrid 结合使用。(您可以尝试使用 stripplot?如果仍然不行,请提供 [mcve] 以便进行测试。) - ImportanceOfBeingErnest
这个问题有解决方案吗?我也遇到了同样的问题。 - Hendrik Wiese
1个回答

6

@ImportanceOfBeingErnest已经在上面的评论中给出了正确答案:在使用sns.catplot()时,不需要同时创建一个独立的FacetGrid,因为sns.catplot()会在调用时自动创建一个FacetGrid

无论如何,当在网格的每个单元格中进行实际绘图时,sns.catplot()会调用另一个 seaborn 函数。该函数可以通过指定 sns.catplot()kind 关键字参数来选择。默认值是kind="strip"

因此,如果您想手动创建一个FacetGrid,然后将sns.catplot()映射到它,但不指定kind,那么您可以使用sns.stripplot()。这确实可以工作,但是 Titanic 数据集对于条形图而言太大了,所以我建议改用小提琴图:

import seaborn as sns
sns.set()

titanic = sns.load_dataset('titanic')

num_vars = ['age', 'fare']
cat_vars = ['pclass', 'embarked', 'sex']

g = sns.PairGrid(data=titanic, x_vars=cat_vars, y_vars=num_vars)
g.map(sns.violinplot)

分面小提琴图

有关更多详细信息,请参见sns.catplot()文档


@Bjarne Thorsted的后续问题: 如何将小提琴图中的箱线图替换为swarmplots?

您仍然可以使用相同的方法,在这种情况下调用g.map()两次。要更改传递给g.map()的绘图函数的默认参数,您可以使用***运算符定义修改后的这些函数的版本:

import seaborn as sns
sns.set()

titanic = sns.load_dataset('titanic')

num_vars = ['age', 'fare']
cat_vars = ['pclass', 'embarked', 'sex']

def violin_empty(*args, **kwargs):
    kwargs['color'] = 'lightblue'
    return sns.violinplot(*args, **kwargs, inner=None)

def swarm_small(*args, **kwargs):
    kwargs['color'] = 'black'
    return sns.swarmplot(*args, **kwargs, size=1) 

g = sns.PairGrid(data=titanic, x_vars=cat_vars, y_vars=num_vars)
g.map(violin_empty)
g.map(swarm_small)

violinplots with swarmplots inside


1
我该如何在每个小提琴图内用swarmplot替换boxplot?我知道可以用点来替换或将其设置为“无”,但是根据教程,添加swarmplot需要提供Axes对象,如果catplot()有多个行或列,则不可能。 - Bjarne Thorsted
1
@Bjarne Thorsted:我已经扩展了我的答案,包括你的问题。不必使用Axes对象。 - Arne

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