我的悬停注释为什么显示 NaN 而不是我的数值?

huangapple go评论65阅读模式
英文:

Why do my hover annotations have NaN instead of my values?

问题

代码部分不需要翻译。以下是您提供的代码的翻译部分:

import yfinance as yf
import mplfinance as mpf
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
import pandas as pd
import numpy as np

# 获取股票数据的日期范围
start_date = "2020-01-01"
end_date = "2023-06-15"

# 获取特斯拉股票数据
tesla_data = yf.download("TSLA", start=start_date, end=end_date)
tesla_weekly_data = tesla_data.resample("W").agg({"Open": "first", "High": "max", "Low": "min", "Close": "last", "Volume": "sum"}).dropna()

# 获取最新的收盘价
latest_price = tesla_weekly_data['Close'][-1]

# 创建额外的图表
close_price = tesla_weekly_data['Close']
apd = mpf.make_addplot(close_price, color='cyan', width=2)

# 绘制蜡烛图
fig, axes = mpf.plot(tesla_weekly_data,
                     type='candle',
                     addplot=apd,
                     style='yahoo',
                     title='特斯拉股票价格',
                     ylabel='价格',
                     xlabel='日期',
                     volume=True,
                     ylabel_lower='成交量',
                     volume_panel=1,
                     figsize=(16, 8),
                     returnfig=True
                     )

# 将y轴标签移到左侧
axes[0].yaxis.tick_left()
axes[1].yaxis.tick_left()

# 调整价格y轴标签的位置
axes[0].yaxis.set_label_coords(-0.08, 0.5)

# 调整成交量y轴标签的位置
axes[1].yaxis.set_label_coords(-0.08, 0.5)

# 设置价格和成交量的y轴标签
axes[0].set_ylabel('价格', rotation=0, labelpad=20)
axes[1].set_ylabel('成交量', rotation=0, labelpad=20)

# 创建图例框
handles = axes[0].get_legend_handles_labels()[0]
red_patch = mpatches.Patch(color='red')
green_patch = mpatches.Patch(color='green')
cyan_patch = mpatches.Patch(color='cyan')
handles = handles[:2] + [red_patch, green_patch, cyan_patch]
labels = ["涨价", "跌价", "收盘价"]
axes[0].legend(handles=handles, labels=labels)

# 添加一个框以显示当前价格
latest_price_text = f"当前价格: ${latest_price:.2f}"
box_props = dict(boxstyle='round', facecolor='white', edgecolor='black', alpha=0.8)
axes[0].text(0.02, 0.95, latest_price_text, transform=axes[0].transAxes, fontsize=12, verticalalignment='top', bbox=box_props)

# 定义悬停标签格式
hover_label_format = [
    ("开盘价: ", lambda x: f"${x:.2f}"),
    ("最高价: ", lambda x: f"${x:.2f}"),
    ("最低价: ", lambda x: f"${x:.2f}"),
    ("收盘价: ", lambda x: f"${x:.2f}"),
    ("成交量: ", lambda x: f"{int(x):,}"),
]

# 创建悬停注释的函数
def hover_annotations(data):
    annot = pd.DataFrame(index=data.index, columns=data.columns)
    annot_visible = False

    texts = []

    def onmove(event):
        nonlocal annot_visible

        if event.inaxes == axes[0]:
            index = int(event.xdata)
            if index >= len(data.index):
                return

            values = data.iloc[index]
            for label, formatter in hover_label_format:
                value = values[label.rstrip(': ')]
                if np.isnan(value):
                    annot.iloc[index][label.rstrip(': ')] = ""
                else:
                    annot.iloc[index][label.rstrip(': ')] = f"{label}{formatter(value)}"

            annot_visible = True
        else:
            annot_visible = False

        for t, text, (x, y) in zip(texts, annot.values, zip([event.xdata] or [], [event.ydata] or [])):
            if isinstance(x, (list, np.ndarray)):
                x = x[0] if len(x) > 0 and not np.isnan(x[0]) else None
            if isinstance(y, (list, np.ndarray)):
                y = y[0] if len(y) > 0 and not np.isnan(y[0]) else None

            if x is not None and y is not None:
                t.set_position((x, y))
                t.set_text('\n'.join(map(str, text)))
                t.set_visible(annot_visible)

        fig.canvas.draw_idle()

    for _ in data.index:
        t = axes[0].text(0, 0, '', visible=False, ha='left', va='top')
        texts.append(t)

    fig.canvas.mpl_connect('motion_notify_event', onmove)

    return annot

# 将悬停注释附加到图表
annotations = hover_annotations(tesla_weekly_data)

# 显示图表
plt.show()

如果您运行此代码,它将绘制特斯拉股票的蜡烛图,并提供悬停功能,以显示开盘价、最高价、最低价、收盘价和成交量的信息。

英文:
import yfinance as yf
import mplfinance as mpf
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
import pandas as pd
import numpy as np
# Dates to get stock data
start_date = "2020-01-01"
end_date = "2023-06-15"
# Fetch Tesla stock data
tesla_data = yf.download("TSLA", start=start_date, end=end_date)
tesla_weekly_data = tesla_data.resample("W").agg({"Open": "first", "High": "max", "Low": "min", "Close": "last", "Volume": "sum"}).dropna()
# Get the latest closing price
latest_price = tesla_weekly_data['Close'][-1]
# Create additional plot
close_price = tesla_weekly_data['Close']
apd = mpf.make_addplot(close_price, color='cyan', width=2)
# Plot the candlestick chart
fig, axes = mpf.plot(tesla_weekly_data,
type='candle',
addplot=apd,
style='yahoo',
title='Tesla Stock Prices',
ylabel='Price',
xlabel='Date',
volume=True,
ylabel_lower='Volume',
volume_panel=1,
figsize=(16, 8),
returnfig=True
)
# Move the y-axis labels to the left side
axes[0].yaxis.tick_left()
axes[1].yaxis.tick_left()
# Adjust the position of the y-axis label for price
axes[0].yaxis.set_label_coords(-0.08, 0.5)
# Adjust the position of the y-axis label for volume
axes[1].yaxis.set_label_coords(-0.08, 0.5)
# Set y-axis label for price and volume
axes[0].set_ylabel('Price', rotation=0, labelpad=20)
axes[1].set_ylabel('Volume', rotation=0, labelpad=20)
# Make the legend box
handles = axes[0].get_legend_handles_labels()[0]
red_patch = mpatches.Patch(color='red')
green_patch = mpatches.Patch(color='green')
cyan_patch = mpatches.Patch(color='cyan')
handles = handles[:2] + [red_patch, green_patch, cyan_patch]
labels = ["Price Up", "Price Down", "Closing Price"]
axes[0].legend(handles=handles, labels=labels)
# Add a box to display the current price
latest_price_text = f"Current Price: ${latest_price:.2f}"
box_props = dict(boxstyle='round', facecolor='white', edgecolor='black', alpha=0.8)
axes[0].text(0.02, 0.95, latest_price_text, transform=axes[0].transAxes, fontsize=12, verticalalignment='top', bbox=box_props)
# Define hover label format
hover_label_format = [
("Open: ", lambda x: f"${x:.2f}"),
("High: ", lambda x: f"${x:.2f}"),
("Low: ", lambda x: f"${x:.2f}"),
("Close: ", lambda x: f"${x:.2f}"),
("Volume: ", lambda x: f"{int(x):,}"),
]
# Function to create hover annotations
def hover_annotations(data):
annot = pd.DataFrame(index=data.index, columns=data.columns)
annot_visible = False
texts = []
def onmove(event):
nonlocal annot_visible
if event.inaxes == axes[0]:
index = int(event.xdata)
if index >= len(data.index):
return
values = data.iloc[index]
for label, formatter in hover_label_format:
value = values[label.rstrip(': ')]
if np.isnan(value):
annot.iloc[index][label.rstrip(': ')] = ""
else:
annot.iloc[index][label.rstrip(': ')] = f"{label}{formatter(value)}"
annot_visible = True
else:
annot_visible = False
for t, text, (x, y) in zip(texts, annot.values, zip([event.xdata] or [], [event.ydata] or [])):
if isinstance(x, (list, np.ndarray)):
x = x[0] if len(x) > 0 and not np.isnan(x[0]) else None
if isinstance(y, (list, np.ndarray)):
y = y[0] if len(y) > 0 and not np.isnan(y[0]) else None
if x is not None and y is not None:
t.set_position((x, y))
t.set_text('\n'.join(map(str, text)))
t.set_visible(annot_visible)
fig.canvas.draw_idle()
for _ in data.index:
t = axes[0].text(0, 0, '', visible=False, ha='left', va='top')
texts.append(t)
fig.canvas.mpl_connect('motion_notify_event', onmove)
return annot
# Attach hover annotations to the plot
annotations = hover_annotations(tesla_weekly_data)
# Display the chart
plt.show()

If you run the code, instead of showing open high, low, close, and volume, its showing an error.

我的悬停注释为什么显示 NaN 而不是我的数值?

答案1

得分: 1

我稍微简化了你的代码。以下对我有效:

import yfinance as yf
import mplfinance as mpf
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
import pandas as pd
import numpy as np

# 获取股票数据的日期
start_date = "2020-01-01"
end_date = "2023-06-15"

# 获取特斯拉股票数据
tesla_data = yf.download("TSLA", start=start_date, end=end_date)
tesla_weekly_data = tesla_data.resample("W").agg(
        {"Open": "first", "High": "max", "Low": "min", "Close": "last", "Volume": "sum"}
    ).dropna()

# 获取最新的收盘价
latest_price = tesla_weekly_data['Close'][-1]

# 创建附加的绘图
close_price = tesla_weekly_data['Close']
apd = mpf.make_addplot(close_price, color='cyan', width=2)

# 绘制蜡烛图
fig, axes = mpf.plot(tesla_weekly_data,
                     type='candle',
                     addplot=apd,
                     style='yahoo',
                     title='特斯拉股票价格',
                     ylabel='价格',
                     xlabel='日期',
                     volume=True,
                     ylabel_lower='交易量',
                     volume_panel=1,
                     figsize=(16, 8),
                     returnfig=True
                     )

# 将y轴标签移动到左侧
axes[0].yaxis.tick_left()
axes[1].yaxis.tick_left()

# 调整价格y轴标签的位置
axes[0].yaxis.set_label_coords(-0.08, 0.5)

# 调整交易量y轴标签的位置
axes[1].yaxis.set_label_coords(-0.08, 0.5)

# 设置价格和交易量的y轴标签
axes[0].set_ylabel('价格', rotation=0, labelpad=20)
axes[1].set_ylabel('交易量', rotation=0, labelpad=20)

# 创建图例框
handles = axes[0].get_legend_handles_labels()[0]
red_patch = mpatches.Patch(color='red')
green_patch = mpatches.Patch(color='green')
cyan_patch = mpatches.Patch(color='cyan')
handles = handles[:2] + [red_patch, green_patch, cyan_patch]
labels = ["涨价", "跌价", "收盘价"]
axes[0].legend(handles=handles, labels=labels)

# 添加框以显示当前价格
latest_price_text = f"当前价格: ${latest_price:.2f}"
box_props = dict(boxstyle='round', facecolor='white', edgecolor='black', alpha=0.8)
axes[0].text(0.02, 0.95, latest_price_text, transform=axes[0].transAxes,
             fontsize=12, verticalalignment='top', bbox=box_props)

# 创建悬停注释的函数
def hover_annotations(data):

    annot_visible = False
    annot = axes[0].text(0, 0, '', visible=False, ha='left', va='top')

    def onmove(event):
        nonlocal annot_visible
        nonlocal annot

        if event.inaxes == axes[0]:
            index = int(event.xdata)
            if index >= len(data.index):
                index = -1
            elif index < 0:
                index = 0
            values = data.iloc[index]
            mytext = (f"{values.name.date().strftime('%m/%d/%Y')}\\n"+
                      f"O: {values['Open']:.2f}\\n"+
                      f"H: {values['High']:.2f}\\n"+
                      f"L: {values['Low']:.2f}\\n"+
                      f"C: {values['Close']:.2f}\\n"+
                      f"V: {values['Volume']:.0f}")

            annot_visible = True
        else:
            mytext = ''
            annot_visible = False

        annot.set_position((event.xdata,event.ydata))
        annot.set_text(mytext)
        annot.set_visible(annot_visible)
        fig.canvas.draw_idle()

    fig.canvas.mpl_connect('motion_notify_event', onmove)

    return annot


# 将悬停注释附加到图表
annotations = hover_annotations(tesla_weekly_data)

# 显示图表
plt.show()
英文:

I've simplified your code a little bit. The following works for me:

import yfinance as yf
import mplfinance as mpf
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
import pandas as pd
import numpy as np

# Dates to get stock data
start_date = &quot;2020-01-01&quot;
end_date = &quot;2023-06-15&quot;

# Fetch Tesla stock data
tesla_data = yf.download(&quot;TSLA&quot;, start=start_date, end=end_date)
tesla_weekly_data = tesla_data.resample(&quot;W&quot;).agg(
        {&quot;Open&quot;: &quot;first&quot;, &quot;High&quot;: &quot;max&quot;, &quot;Low&quot;: &quot;min&quot;, &quot;Close&quot;: &quot;last&quot;, &quot;Volume&quot;: &quot;sum&quot;}
    ).dropna()

# Get the latest closing price
latest_price = tesla_weekly_data[&#39;Close&#39;][-1]

# Create additional plot
close_price = tesla_weekly_data[&#39;Close&#39;]
apd = mpf.make_addplot(close_price, color=&#39;cyan&#39;, width=2)

# Plot the candlestick chart
fig, axes = mpf.plot(tesla_weekly_data,
                     type=&#39;candle&#39;,
                     addplot=apd,
                     style=&#39;yahoo&#39;,
                     title=&#39;Tesla Stock Prices&#39;,
                     ylabel=&#39;Price&#39;,
                     xlabel=&#39;Date&#39;,
                     volume=True,
                     ylabel_lower=&#39;Volume&#39;,
                     volume_panel=1,
                     figsize=(16, 8),
                     returnfig=True
                     )

# Move the y-axis labels to the left side
axes[0].yaxis.tick_left()
axes[1].yaxis.tick_left()

# Adjust the position of the y-axis label for price
axes[0].yaxis.set_label_coords(-0.08, 0.5)

# Adjust the position of the y-axis label for volume
axes[1].yaxis.set_label_coords(-0.08, 0.5)

# Set y-axis label for price and volume
axes[0].set_ylabel(&#39;Price&#39;, rotation=0, labelpad=20)
axes[1].set_ylabel(&#39;Volume&#39;, rotation=0, labelpad=20)

# Make the legend box
handles = axes[0].get_legend_handles_labels()[0]
red_patch = mpatches.Patch(color=&#39;red&#39;)
green_patch = mpatches.Patch(color=&#39;green&#39;)
cyan_patch = mpatches.Patch(color=&#39;cyan&#39;)
handles = handles[:2] + [red_patch, green_patch, cyan_patch]
labels = [&quot;Price Up&quot;, &quot;Price Down&quot;, &quot;Closing Price&quot;]
axes[0].legend(handles=handles, labels=labels)

# Add a box to display the current price
latest_price_text = f&quot;Current Price: ${latest_price:.2f}&quot;
box_props = dict(boxstyle=&#39;round&#39;, facecolor=&#39;white&#39;, edgecolor=&#39;black&#39;, alpha=0.8)
axes[0].text(0.02, 0.95, latest_price_text, transform=axes[0].transAxes,
             fontsize=12, verticalalignment=&#39;top&#39;, bbox=box_props)

# Function to create hover annotations
def hover_annotations(data):

    annot_visible = False
    annot = axes[0].text(0, 0, &#39;&#39;, visible=False, ha=&#39;left&#39;, va=&#39;top&#39;)

    def onmove(event):
        nonlocal annot_visible
        nonlocal annot

        if event.inaxes == axes[0]:
            index = int(event.xdata)
            if index &gt;= len(data.index):
                index = -1
            elif index &lt; 0:
                index = 0
            values = data.iloc[index]
            mytext = (f&quot;{values.name.date().strftime(&#39;%m/%d/%Y&#39;):}\n&quot;+
                      f&quot;O: {values[&#39;Open&#39;]:.2f}\n&quot;+
                      f&quot;H: {values[&#39;High&#39;]:.2f}\n&quot;+
                      f&quot;L: {values[&#39;Low&#39;]:.2f}\n&quot;+
                      f&quot;C: {values[&#39;Close&#39;]:.2f}\n&quot;+
                      f&quot;V: {values[&#39;Volume&#39;]:.0f}&quot;
                     )

            annot_visible = True
        else:
            mytext = &#39;&#39;
            annot_visible = False

        annot.set_position((event.xdata,event.ydata))
        annot.set_text(mytext)
        annot.set_visible(annot_visible)
        fig.canvas.draw_idle()

    fig.canvas.mpl_connect(&#39;motion_notify_event&#39;, onmove)

    return annot


# Attach hover annotations to the plot
annotations = hover_annotations(tesla_weekly_data)

# Display the chart
plt.show()

I don't know what the problem was, but I completely got rid of the array of texts and the DataFrame annot (but I reused the name annot for a single annotation, what you were previously calling t). I also got rid of all the looping through these things, and the complicated formatting lambdas which seemed to me very unneccessary. At any rate, the above works for me.

huangapple
  • 本文由 发表于 2023年6月16日 09:32:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/76486448.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定