matplotlib事件.xdata超出时间序列范围

wqsoz72f  于 2023-06-23  发布在  其他
关注(0)|答案(2)|浏览(102)

在绘制pandas.Timeseries时,使用matplotlibevent.xdata有问题,我试图重现very related question中提出的答案,但得到了一个非常奇怪的行为。
下面是代码,适用于python3,并在on_click()函数中添加了更多的内容:

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

import matplotlib.dates as mdates

def on_click(event):
    if event.inaxes is not None:
        # provide raw and converted x data
        print(f"{event.xdata} --> {mdates.num2date(event.xdata)}")
    # add a vertical line at clicked location
    line = ax.axvline(x=event.xdata)
    plt.draw()

t = pd.date_range('2015-11-01', '2016-01-06', freq='H')
y = np.random.normal(0, 1, t.size).cumsum()

df = pd.DataFrame({'Y':y}, index=t)

fig, ax = plt.subplots()
line = None
df.plot(ax=ax)
fig.canvas.mpl_connect('button_press_event', on_click)
plt.show()

如果我启动它,我会得到下面的图表,预期日期范围在11月11日和12月12日之间。2015年及1月2016,如窗口页脚中提供的光标位置信息(此处为2015-11-01 10:00),以及垂直线的正确位置:

但是,命令行输出如下:

C:\Users\me\Documents\code\>python matplotlib_even.xdate_num2date.py
402189.6454115977 --> 1102-02-27 15:29:23.562039+00:00
402907.10400704964 --> 1104-02-15 02:29:46.209088+00:00

这些event.xdata值显然超出了输入数据范围和x轴数据范围,并且不能用于以后的使用(例如,尝试找到序列中最接近的y值)。

有谁知道我如何得到正确的xdata

fiei3ece

fiei3ece1#

matplotlib/pandas处理您链接的相关问题的答案和现在之间的日期时间信息的方式一定发生了变化。我无法解释原因,但我找到了解决问题的方法。
我深入研究了在状态栏左下角显示坐标的代码,我发现当你绘制一个时间序列时,pandas会修补打印此信息的函数,并将其替换为此函数。
从这里可以看到,需要将float值转换为Period对象。

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

def on_click(event):
    print(pd.Period(ordinal=int(event.xdata), freq='H'))

t = pd.date_range('2015-11-01', '2016-01-06', freq='H')
y = np.random.normal(0, 1, t.size).cumsum()

df = pd.DataFrame({'Y': y}, index=t)

fig, ax = plt.subplots()
df.plot(ax=ax)
fig.canvas.mpl_connect('button_press_event', on_click)
plt.show()
qyyhg6bp

qyyhg6bp2#

我想把这个问题作为注解之一来评论一下,即print(f”{event.xdata} --> {event. inaxis.format_coord(event.xdata,event.ydata)}”)是关于xaxis是datetime时如何处理游标的答案。我已经在谷歌上搜索了好几天,但没有成功。似乎是最好的答案不是;但这是我附上一个简单的代码示例来说明这一点。代码如下:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
def split_f_c(w):
    xval=w.split(" ")[0]
    val=xval.split("=")[1]
    return val
def on_click(event):
    print("wrong answer with plt.plot:\n",\
          pd.Period(ordinal=int(event.xdata), freq='H'))
    print(f"{event.xdata} --> {event.inaxes.format_coord(event.xdata,event.ydata)}")
    w=event.inaxes.format_coord(event.xdata,event.ydata)
    print("xvalue:",split_f_c(w))
    lo=ax.get_xlim()[0]
    hi=ax.get_xlim()[1]
    w=event.inaxes.format_coord(lo,hi)
    lowest=split_f_c(w)
    w=event.inaxes.format_coord(hi,lo)
    highest=split_f_c(w)
    print("in range ",lowest, highest)
t = pd.date_range('2015-11-01', '2016-01-06', freq='H')
y = np.random.normal(0, 1, t.size).cumsum()
df = pd.DataFrame({'Y': y}, index=t)
fig, ax = plt.subplots()
#df.plot(ax=ax)
plt.plot(t,y)
fig.canvas.mpl_connect('button_press_event', on_click)
plt.show()

相关问题