在 seaborn 中的特定 position/annotate 个 Facetgrid 处画一条线

Draw a line at specific position/annotate a Facetgrid in seaborn

A 已经通过以下方式在 seaborn 中生成了带有 Facetgrid 的箱线图

# Import the dataset
tips = sns.load_dataset("tips")

# Plot using FacetGrid, separated by smoke
plt.style.use('ggplot')
g = sns.FacetGrid(tips, col="smoker", size=5, aspect=1.5)
g.map(sns.boxplot, "sex", "total_bill", palette='viridis', order=['Male', 'Female'])
plt.show()

我现在想在每个图中绘制不同的水平线。例如,左侧图中的一条水平线(坐标为(0,10)),另一条水平线(坐标为(0,30))右侧图中只有

我该怎么做?

您可以使用 FacetGrid.axes 获取 FacetGrid 中使用的轴列表,其中 returns 使用了轴。然后,您可以使用这些轴执行所有正常的 matplotlib 操作,例如 axhline for horizontal lines, or plt.text 用于将文本放在轴上:

import seaborn as sns
import matplotlib.pyplot as plt
tips = sns.load_dataset("tips")

# Plot using Facegrid, separated by smoke
plt.style.use('ggplot')
g = sns.FacetGrid(tips, col="smoker", size=5, aspect=1.5)
g.map(sns.boxplot, "sex", "total_bill", palette='viridis', order=['Male', 'Female'])

ax1, ax2 = g.axes[0]

ax1.axhline(10, ls='--')
ax2.axhline(30, ls='--')

ax1.text(0.5,25, "Some text")
ax2.text(0.5,25, "Some text")

plt.show()

axhlinehlines。简单示例:

chart = sns.relplot(x="x", y="y", kind="line", data=df)

chart.axes[0][0].axhline(y = 10, color='black', linewidth=2, alpha=.7)
chart.axes[0][0].hlines( y = 20, color='black', linewidth=2, alpha=.7, 
                         xmin = 30, xmax = 50) 

似乎 hlines 允许 min-max (documentation) 但 axhline 不允许。

此外,如果你有一堆网格,你想给所有网格添加一条水平线(比如在 y=10 处),那么你可以只 "map" "plt.axhline" 和你的网格对象:

import seaborn as sns
import matplotlib.pyplot as plt
tips = sns.load_dataset("tips")
# Plot using Facegrid, separated by smoke
plt.style.use('ggplot')
g = sns.FacetGrid(tips, col="smoker", size=5, aspect=1.5)
g.map(sns.boxplot, "sex", "total_bill", palette='viridis', order=['Male', 'Female'])

g.map(plt.axhline, y=10, ls='--', c='red')

如果您想对 cols 中的数字做同样的事情,只需添加到最上面的答案即可。

g = sns.FacetGrid(df_long, col="variable", size=5, aspect=1.5,col_wrap=1,sharey=False)
# df_long is a long table with 3 variables
g.map(sns.boxplot, "label", "value", palette='Set2')
g.axes[0].axhline(1, ls='--',c='r')
g.axes[1].axhline(1, ls='--',c='r')
g.axes[2].axhline(0.5, ls='--',c='r')
g.map(plt.xticks, rotation=70) 
plt.show()

result

  • seaborn v0.11.0开始推荐使用像seaborn.catplot instead of seaborn.FacetGrid
  • 这样的图形级函数
  • 如果每个 axes 需要不同的行位置和注释,那么最简单的实现是将位置和文本放入 dict,并展平返回的 axes在创建情节时。
    • 使用枚举访问 dict
    • 中的每组值
    • 这确实需要知道输出图的顺序,因此图需要 运行,然后创建 dict 和循环以添加线条和注释。
  • 或者,请参阅此 ,它使用 g.row_namesg.col_names 提取每个轴的行和列名称。行名和列名可以用keys.
  • 对多条垂直线或水平线使用matplotlib.pyplot.vlines and matplotlib.pyplot.hlines
import seaborn as sns

tips = sns.load_dataset("tips")
g = sns.catplot(kind='box', data=tips, col='smoker', row='sex', x='sex', y='total_bill', height=3)

# dict of line positions and annotations
la = {0: [5, 0.4, 0.75, 40, 'text_a'], 1: [10, 0.5, 0.75, 40, 'text_b'],
      2: [25, 0.6, 0.75, 40, 'text_c'], 3: [35, 0.7, 0.75, 40, 'text_d']}

# flatten axes into a 1-d array
axes = g.axes.flatten()

# iterate through the axes
for i, ax in enumerate(axes):
    ax.axhline(la[i][0], ls='--', c='green')
    ax.axvline(la[i][1], ls='--', c='purple')
    ax.text(la[i][2], la[i][3], la[i][4], c='orange')