Python 如何在pyplot中自动注释最大值?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/43374920/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 22:58:14  来源:igfitidea点击:

How to automatically annotate maximum value in pyplot?

pythonpandasnumpymatplotlib

提问by shadewolf

I'm trying to figure out how I can automatically annotate the maximum value in a figure window. I know you can do this by manually entering in x,y coordinates to annotate whatever point you want using the .annotate()method, but I want the annotation to be automatic, or to find the maximum point by itself.

我想弄清楚如何在图形窗口中自动注释最大值。我知道您可以通过手动输入 x,y 坐标来使用该.annotate()方法注释您想要的任何点,但我希望注释是自动的,或者自己找到最大点。

Here's my code so far:

到目前为止,这是我的代码:

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from pandas import Series, DataFrame

df = pd.read_csv('macrodata.csv') #Read csv file into dataframe
years = df['year'] #Get years column
infl = df['infl'] #Get inflation rate column

fig10 = plt.figure()
win = fig10.add_subplot(1,1,1)
fig10 = plt.plot(years, infl, lw = 2)

fig10 = plt.xlabel("Years")
fig10 = plt.ylabel("Inflation")
fig10 = plt.title("Inflation with Annotations")

Here's the figure that it generates

这是它生成的图

回答by ImportanceOfBeingErnest

If xand yare the arrays to plot, you get the coordinates of the maximum via

如果xy是要绘制的数组,则可以通过以下方式获得最大值的坐标

xmax = x[numpy.argmax(y)]
ymax = y.max()

This can be incorporated into a function that you may simply call with your data.

这可以合并到一个函数中,您可以简单地使用您的数据调用该函数。

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(-2,8, num=301)
y = np.sinc((x-2.21)*3)


fig, ax = plt.subplots()
ax.plot(x,y)

def annot_max(x,y, ax=None):
    xmax = x[np.argmax(y)]
    ymax = y.max()
    text= "x={:.3f}, y={:.3f}".format(xmax, ymax)
    if not ax:
        ax=plt.gca()
    bbox_props = dict(boxstyle="square,pad=0.3", fc="w", ec="k", lw=0.72)
    arrowprops=dict(arrowstyle="->",connectionstyle="angle,angleA=0,angleB=60")
    kw = dict(xycoords='data',textcoords="axes fraction",
              arrowprops=arrowprops, bbox=bbox_props, ha="right", va="top")
    ax.annotate(text, xy=(xmax, ymax), xytext=(0.94,0.96), **kw)

annot_max(x,y)


ax.set_ylim(-0.3,1.5)
plt.show()

enter image description here

在此处输入图片说明

回答by Anil_M

I don't have data of macrodata.csvto go with. However, generically, assuming you have xand yaxis data as an list, you can use following method to get auto positioning of max.

我没有可使用的数据macrodata.csv。然而,一般,假设你有xy轴数据作为一个列表,你可以用下面的方法来获得自动定位max

Working Code:

工作代码:

import numpy as np
import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.add_subplot(111)

x=[1,2,3,4,5,6,7,8,9,10]
y=[1,1,1,2,10,2,1,1,1,1]
line, = ax.plot(x, y)

ymax = max(y)
xpos = y.index(ymax)
xmax = x[xpos]

ax.annotate('local max', xy=(xmax, ymax), xytext=(xmax, ymax+5),
            arrowprops=dict(facecolor='black', shrink=0.05),
            )

ax.set_ylim(0,20)
plt.show()

Plot :
enter image description here

阴谋 :
在此处输入图片说明

回答by Alex

Something like this would work:

像这样的事情会起作用:

infl_max_index = np.where(infl == max(infl)) #get the index of the maximum inflation
infl_max = infl[infl_max_index] # get the inflation corresponding to this index
year_max = year[infl_max_index] # get the year corresponding to this index

plt.annotate('max inflation', xy=(year_max, infl_max))

回答by Jabro Jacob

The method proposed by @ImportanceOfBeingErnest in his responseis really neat, but it doesn't work if the data is within a panda data-frame whose index isn't a zero based uniform index ([0,1,2,..,N]), and it is desired to plot against the index -whose values are the x's-.

@ImportanceOfBeingErnest 在他的回复中提出的方法非常简洁,但是如果数据位于索引不是基于零的统一索引 ([0,1,2,.., N]),并且需要针对索引(其值为 x 的值)进行绘图。

I took the liberty to adapt the aforementioned solution and use it with pandas plotfunction. I also wrote the symmetric minfunction.

我冒昧地调整了上述解决方案并将其与 pandasplot功能一起使用。我还写了对称min函数。

def annot_max(x,y, ax=None):
    maxIxVal = np.argmax(y);
    zeroBasedIx = np.argwhere(y.index==maxIxVal).flatten()[0];
    xmax = x[zeroBasedIx];
    ymax = y.max()
    text= "k={:d}, measure={:.3f}".format(xmax, ymax)
    if not ax:
        ax=plt.gca()
    bbox_props = dict(boxstyle="round,pad=0.3", fc="w", ec="k", lw=0.72)
    arrowprops=dict(arrowstyle="-",connectionstyle="arc3,rad=0.1")
    kw = dict(xycoords='data',textcoords="axes fraction",
              arrowprops=arrowprops, bbox=bbox_props, ha="right", va="top")
    ax.annotate(text, xy=(xmax, ymax), xytext=(0.94,0.90), **kw)

def annot_min(x,y, ax=None):
    minIxVal = np.argmin(y);
    zeroBasedIx = np.argwhere(y.index==minIxVal).flatten()[0];
    xmin = x[zeroBasedIx];
    ymin = y.min()
    text= "k={:d}, measure={:.3f}".format(xmin, ymin)
    if not ax:
        ax=plt.gca()
    bbox_props = dict(boxstyle="round,pad=0.3", fc="w", ec="k", lw=0.72)
    arrowprops=dict(arrowstyle="-",connectionstyle="arc3,rad=0.1")
    kw = dict(xycoords='data',textcoords="axes fraction",
              arrowprops=arrowprops, bbox=bbox_props, ha="right", va="top")
    ax.annotate(text, xy=(xmin, ymin), xytext=(0.94,0.90), **kw)

Usage is straightforward, for example:

用法很简单,例如:

ax = df[Series[0]].plot(grid=True, use_index=True, \
                  title=None);
annot_max(df[Series[0]].index,df[Series[0]],ax);
plt.show();

I hope this would be of any help to anyone.

我希望这对任何人都有帮助。