【问题标题】:How to plot multiple Seaborn Jointplot with annotation in Subplot如何在子图中使用注释绘制多个 Seaborn Jointplot
【发布时间】:2021-12-07 08:36:01
【问题描述】:

目标是为带有相关性的联合图注释创建子图。但是plt.show()的时候,图是分开显示的。

我可以知道如何解决这个问题吗?

import numpy as np
import pandas as pd
import scipy.stats as stats
import seaborn as sns
import matplotlib.pyplot as plt
ncols=['ra','rb','a','b','c','d']

df=pd.DataFrame(np.random.rand(100,len(ncols)),columns=ncols)
nvars=['a','b','c','d']
rt=['a','b']
fig, axs = plt.subplots(len(rt),len(nvars))
for idx_rt, nrt in enumerate(rt):
  for idx_var, nvar  in enumerate(nvars):
    g=sns.jointplot(data=df, y=nrt, x=nvar,kind = 'reg',ax=axs[idx_rt,idx_var])
    r, p = stats.pearsonr(df[nrt], df[nvar])
    g.ax_joint.annotate(f'$\\rho = {r:.3f}, p = {p:.3f}$',
      xy=(0.1, 0.9), xycoords='axes fraction',
      ha='left', va='center',
      bbox={'boxstyle': 'round', 'fc': 'powderblue', 'ec': 'navy'})
    

plt.tight_layout()
plt.show()

【问题讨论】:

  • 我觉得this answer 很有帮助
  • TypeError 是因为ax 后面多了一个逗号。替换为for ax in axes.flat: 避免错误(虽然不在同一个网格上绘制)

标签: python plot seaborn subplot


【解决方案1】:

在此 answer 之上构建您应该通过组合自定义 SeabornFig2Grid 类和 matplotlib GridSpec 来取得成功。这是您的玩具示例:

  • 首先定义SeabornFig2Grid

    类 SeabornFig2Grid():

     def __init__(self, seaborngrid, fig,  subplot_spec):
         self.fig = fig
         self.sg = seaborngrid
         self.subplot = subplot_spec
         if isinstance(self.sg, sns.axisgrid.FacetGrid) or \
             isinstance(self.sg, sns.axisgrid.PairGrid):
             self._movegrid()
         elif isinstance(self.sg, sns.axisgrid.JointGrid):
             self._movejointgrid()
         self._finalize()
    
     def _movegrid(self):
         """ Move PairGrid or Facetgrid """
         self._resize()
         n = self.sg.axes.shape[0]
         m = self.sg.axes.shape[1]
         self.subgrid = gridspec.GridSpecFromSubplotSpec(n,m, subplot_spec=self.subplot)
         for i in range(n):
             for j in range(m):
                 self._moveaxes(self.sg.axes[i,j], self.subgrid[i,j])
    
     def _movejointgrid(self):
         """ Move Jointgrid """
         h= self.sg.ax_joint.get_position().height
         h2= self.sg.ax_marg_x.get_position().height
         r = int(np.round(h/h2))
         self._resize()
         self.subgrid = gridspec.GridSpecFromSubplotSpec(r+1,r+1, subplot_spec=self.subplot)
    
         self._moveaxes(self.sg.ax_joint, self.subgrid[1:, :-1])
         self._moveaxes(self.sg.ax_marg_x, self.subgrid[0, :-1])
         self._moveaxes(self.sg.ax_marg_y, self.subgrid[1:, -1])
    
     def _moveaxes(self, ax, gs):
         #https://stackoverflow.com/a/46906599/4124317
         ax.remove()
         ax.figure=self.fig
         self.fig.axes.append(ax)
         self.fig.add_axes(ax)
         ax._subplotspec = gs
         ax.set_position(gs.get_position(self.fig))
         ax.set_subplotspec(gs)
    
     def _finalize(self):
         plt.close(self.sg.fig)
         self.fig.canvas.mpl_connect("resize_event", self._resize)
         self.fig.canvas.draw()
    
     def _resize(self, evt=None):
         self.sg.fig.set_size_inches(self.fig.get_size_inches())
    
  • 然后在同一个网格中绘制你的地块

import itertools 
import matplotlib.gridspec as gridspec
# import seaborn as sns; sns.set()
import numpy as np
import pandas as pd
import scipy.stats as stats
import seaborn as sns
import matplotlib.pyplot as plt
ncols=['ra','rb','a','b','c','d']

df=pd.DataFrame(np.random.rand(100,len(ncols)),columns=ncols)
nvars=['a','b','c','d']
rt=['a','b']

# A JointGrid
fig = plt.figure(figsize=(13,8))
gs = gridspec.GridSpec(len(rt),len(nvars))

for i, idxs in enumerate(itertools.product(rt, nvars)):
    nrt, nvar = idxs
    g=sns.jointplot(data=df, y=nrt, x=nvar,kind = 'reg')#, space=0,ax=axs[idx_rt,idx_var])
    r, p = stats.pearsonr(df[nrt], df[nvar])
    g.ax_joint.annotate(f'$\\rho = {r:.3f}, p = {p:.3f}$',
      xy=(0.1, 0.9), xycoords='axes fraction',
      ha='left', va='center',
      bbox={'boxstyle': 'round', 'fc': 'powderblue', 'ec': 'navy'})
    mg = SeabornFig2Grid(g, fig, gs[i])

gs.tight_layout(fig)
#gs.update(top=0.7)

plt.show()

结果如下:

这就是你要找的吗?

【讨论】:

  • @rpb 这能回答你的问题吗?
猜你喜欢
  • 1970-01-01
  • 2015-07-06
  • 2016-05-04
  • 1970-01-01
  • 1970-01-01
  • 2015-10-02
  • 2021-02-26
  • 2022-10-12
  • 2018-09-15
相关资源
最近更新 更多