在 seaborn 中的特定位置画一条线/注释 Facetgrid
Posted
技术标签:
【中文标题】在 seaborn 中的特定位置画一条线/注释 Facetgrid【英文标题】:Draw a line at specific position/annotate a Facetgrid in seaborn 【发布时间】:2019-01-24 06:13:15 【问题描述】: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))仅在右侧的图中。
我该怎么做呢?
【问题讨论】:
【参考方案1】:您可以使用 FacetGrid.axes
获取 FacetGrid 中使用的轴列表,该列表返回使用的轴。然后,您可以使用这些轴执行所有正常的 matplotlib 操作,例如 axhline
用于水平线,或 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()
【讨论】:
【参考方案2】:此外,如果您有一堆网格要向所有网格添加一条水平线(例如 y=10),那么您只需将“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')
【讨论】:
【参考方案3】:有axhline
和hlines
。简单例子:
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
允许最小-最大 (documentation) 但axhline
不允许。
【讨论】:
【参考方案4】:如果你想对 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
【讨论】:
【参考方案5】: 建议从seaborn v0.11.0
使用像seaborn.catplot
这样的图形级函数,而不是seaborn.FacetGrid
如果每个axes
需要不同的行位置和注释,那么最简单的实现是将位置和文本放入dict
,并在创建绘图时展平返回的axes
。
使用枚举从dict
访问每组值
这确实需要知道输出图的顺序,因此需要运行该图,然后创建 dict
并循环添加线条和注释。
或者,请参阅此answer,它使用g.row_names
和g.col_names
提取每个轴的行名和列名。行列名可以用keys
。
将matplotlib.pyplot.vlines
和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')
【讨论】:
以上是关于在 seaborn 中的特定位置画一条线/注释 Facetgrid的主要内容,如果未能解决你的问题,请参考以下文章