使用python和matplotlib注释行尾

ves*_*and 10 python matplotlib

使用数据框和基本图如下:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

np.random.seed(123456)
rows = 75
df = pd.DataFrame(np.random.randint(-4,5,size=(rows, 3)), columns=['A', 'B', 'C'])
datelist = pd.date_range(pd.datetime(2017, 1, 1).strftime('%Y-%m-%d'), periods=rows).tolist()
df['dates'] = datelist 
df = df.set_index(['dates'])
df.index = pd.to_datetime(df.index)
df = df.cumsum()

df.plot()
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

注释线上最后几点的最佳方法是什么,以便得到下面的结果?

在此输入图像描述

Imp*_*est 11

为了注释点使用ax.annotate().在这种情况下,指定要单独注释的坐标是有意义的.即,y坐标是线的最后一个点(可以从中得到line.get_ydata()[-1])的数据坐标,而x坐标独立于数据,应该是轴的右侧(即1轴坐标).然后,您可能还希望稍微偏移文本,使其不与轴重叠.

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

rows = 75
df = pd.DataFrame(np.random.randint(-4,5,size=(rows, 3)), columns=['A', 'B', 'C'])
datelist = pd.date_range(pd.datetime(2017, 1, 1).strftime('%Y-%m-%d'), periods=rows).tolist()
df['dates'] = datelist 
df = df.set_index(['dates'])
df.index = pd.to_datetime(df.index)
df = df.cumsum()

ax = df.plot()

for line, name in zip(ax.lines, df.columns):
    y = line.get_ydata()[-1]
    ax.annotate(name, xy=(1,y), xytext=(6,0), color=line.get_color(), 
                xycoords = ax.get_yaxis_transform(), textcoords="offset points",
                size=14, va="center")

plt.show()
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述


sac*_*cuL 9

方法一

这是一种方法,或者至少是一种方法,您可以使用该plt.annotate方法以任何您想要的方式适应美学:

[编辑]:如果您要使用第一个这样的方法,则ImportanceOfBeingErnest 的答案中概述的方法比我提出的要好。

df.plot()

for col in df.columns:
    plt.annotate(col,xy=(plt.xticks()[0][-1]+0.7, df[col].iloc[-1]))

plt.show()
Run Code Online (Sandbox Code Playgroud)

阴谋

对于xy参数,即文本的 x 和 y 坐标,我选择了 中的最后一个 x 坐标plt.xticks(),并添加了 0.7 使其位于 x 轴之外,但您可以根据需要使其更近或更远.

方法二

您也可以只使用正确的 y 轴,并用 3 条线标记它。例如:

fig, ax = plt.subplots()
df.plot(ax=ax)
ax2 = ax.twinx()
ax2.set_ylim(ax.get_ylim())
ax2.set_yticks([df[col].iloc[-1] for col in df.columns])
ax2.set_yticklabels(df.columns)

plt.show()
Run Code Online (Sandbox Code Playgroud)

这为您提供了以下情节:

plot2 注释为 y

  • 您可以去除刺以获得更大的效果。很不错的主意。 (2认同)

nev*_*ves 9

我从其他答案中得到了一些提示,并相信这是最简单的解决方案。

这是一个改进折线图标签的通用函数。其优点是:

  • 你不需要弄乱原始的 DataFrame,因为它是在折线图上工作的,
  • 它将使用已经设置的图例标签,
  • 移除框架,
  • 只需复制并粘贴它即可改进您的图表:-)

您可以在创建任何行字符后调用它:

def improve_legend(ax=None):
    if ax is None:
        ax = plt.gca()

    for spine in ax.spines:
        ax.spines[spine].set_visible(False)
        
    for line in ax.lines:
        data_x, data_y = line.get_data()
        right_most_x = data_x[-1]
        right_most_y = data_y[-1]
        ax.annotate(
            line.get_label(),
            xy=(right_most_x, right_most_y),
            xytext=(5, 0),
            textcoords="offset points",
            va="center",
            color=line.get_color(),
        )
    ax.legend().set_visible(False)
Run Code Online (Sandbox Code Playgroud)

这是原始图表

原图

现在你只需要调用该函数来改进你的绘图:

ax = df.plot()
improve_legend(ax)
Run Code Online (Sandbox Code Playgroud)

新图表:

改进的情节

请注意,如果一行末尾有空值,它可能无法正常工作。