【问题标题】:Plotnine (ggplot) : Annotation outside of plotting areaPlotnine(ggplot):绘图区域外的注释
【发布时间】:2021-11-10 13:43:31
【问题描述】:

我在plotnine 中有以下情节。我想在 y 轴左侧添加一个显示系列平均值的标签(基本上与 y 轴标签一致)。如果标签的形状如下,指向平均线,那就更好了。这可能吗?

import numpy as np
import pandas as pd
import datetime
from plotnine import *


df = pd.DataFrame({
    'date':pd.date_range(start='1/1/2000', periods=10, freq='A'),
    'a': np.random.choice(range(20),10),
    'b': np.random.choice(range(20),10),
})

mean_a = df['a'].mean()
mean_b = df['b'].mean()

df = pd.melt(df,id_vars=['date'])

p = (ggplot(df, aes(x='date', y='value', fill='variable'))
  + theme_light()
  + geom_col(position='dodge', alpha=0.8)
  + geom_hline(yintercept=mean_a, linetype='dotted', color='#770d50', size=1.5)
  + geom_hline(yintercept=mean_b, linetype='dotted', color='#0055b3', size=1.5)
  + annotate('label', x=datetime.datetime(2010, 10, 1), y=mean_a, label='{:.1f}'.format(mean_a), color='#770d50', size=8, label_size=0.2)
  + annotate('label', x=datetime.datetime(2010, 10, 1), y=mean_b, label='{:.1f}'.format(mean_b), color='#0055b3', size=8, label_size=0.2)
  + annotate('label', x=datetime.datetime(2011, 1, 1), y=mean_b, label='')
  + scale_x_date(expand=(0,0), labels= lambda l: [v.strftime("%Y") for v in l])
  + scale_fill_manual(('#770d50','#0055b3'))
)
p

【问题讨论】:

    标签: python ggplot2 plotnine


    【解决方案1】:

    here 所述,您可以使用 ggplot 对象的draw 方法获取 matplotlib 图形。然后,您可以使用轴和传统的 matplotlib 函数来绘制所需的注释,使用 ax.textax.annotate 函数,如下所示。您可能需要使用文本的实际 x 位置。

    # original graph
    p = (ggplot(df, aes(x='date', y='value', fill='variable'))
      + theme_light()
      + geom_col(position='dodge', alpha=0.8)
      + geom_hline(yintercept=mean_a, linetype='dotted', color='#770d50', size=1.5)
      + geom_hline(yintercept=mean_b, linetype='dotted', color='#0055b3', size=1.5)
      + annotate('label', x=datetime.datetime(2010, 10, 1), y=mean_a, label='{:.1f}'.format(mean_a), color='#770d50', size=8, label_size=0.2)
      + annotate('label', x=datetime.datetime(2010, 10, 1), y=mean_b, label='{:.1f}'.format(mean_b), color='#0055b3', size=8, label_size=0.2)
      + annotate('label', x=datetime.datetime(2011, 1, 1), y=mean_b, label='')
      + scale_x_date(expand=(0,0), labels= lambda l: [v.strftime("%Y") for v in l])
      + scale_fill_manual(('#770d50','#0055b3'))
    )
    
    # graph with annotation
    fig = p.draw() # get the matplotlib figure object
    ax = fig.axes[0] # get the matplotlib axis (may be more than one if faceted)
    x_ticks = ax.get_xticks() # get the original x tick locations
    x_loc = x_ticks.min() - (sorted(x_ticks)[1] - sorted(x_ticks)[0])*.75 # location for the annotation based on the original xticks
    # annotation for mean_a using text
    ax.text(x_loc,mean_a,'{:.2f}'.format(mean_a),
            horizontalalignment='right',verticalalignment='center',
            color='#770d50')
    # annotation for mean_b using annotate with an arrow
    ax.annotate(xy=(x_ticks.min(),mean_b),
                xytext=(x_loc,mean_b+.5),text='{:.2f}'.format(mean_b),
            horizontalalignment='right',verticalalignment='center',
            arrowprops={'arrowstyle':'->'},
            color='#0055b3')
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-08-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-09
      • 1970-01-01
      • 2012-04-29
      • 2023-03-22
      相关资源
      最近更新 更多