You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决Python Shiny中Matplotlib直方图绘制报错问题?

问题描述

我是Python和Shiny的新手,在Python Shiny中使用Matplotlib绘制直方图时遇到了问题。以下是我的应用代码:

from shiny import App, ui, reactive, render
import numpy as np
import matplotlib.pyplot as plt

app_ui = ui.page_fluid(
    ui.panel_title("My Shiny Test Application"),
    ui.layout_sidebar(
      ui.panel_sidebar(
        ui.input_slider(
          "nr_of_observations", 
          "Number of observations",
          min = 0,
          max = 100,
          value = 30
        )
      ),
      ui.panel_main(
        ui.navset_tab(
          ui.nav(
            "Scatter",
            ui.output_plot("my_scatter")
          ),
          ui.nav(
            "Histogram",
            ui.output_plot("my_histogram")
          ),
          ui.nav(
            "Summary",
            ui.output_text_verbatim("my_summary"),
          )
        )
      )
    )
  )


def server(input, output, session):
  @reactive.Calc
  def random_data():
    return np.random.rand(input.nr_of_observations())
  
  @output
  @render.plot
  def my_scatter():
    return plt.scatter(random_data(), random_data())
  
  @output
  @render.plot
  def my_histogram():
    return plt.hist(random_data())

  @output
  @render.text
  def my_summary():
    return(random_data())
  
app = App(app_ui, server)

其中散点图可正常显示,但直方图出现无法理解的报错。而在单独脚本中运行以下代码时一切正常:

import matplotlib.pyplot as plt
import numpy as np
random_numbers = np.random.rand(20)
plt.scatter(random_numbers, random_numbers)
plt.show()

plt.close()
plt.hist(random_numbers)
plt.show()
问题分析与解决提示
  • 核心问题:返回值类型不匹配
    plt.scatter() 返回的是PathCollection对象,@render.plot可以识别并正确渲染;但plt.hist()返回的是元组(n, bins, patches)(包含直方图计数、区间、图形元素),@render.plot无法直接处理该元组,导致报错。

  • 次要问题:全局绘图状态污染
    单独脚本中用plt.close()清理了全局绘图状态,但Shiny应用未做类似处理,多次切换标签或调整滑块时,全局plt的状态可能混乱,加重渲染问题。

  • 额外风险:空数组处理
    当滑块值为0时,np.random.rand(0)生成空数组,直接传入plt.hist()会触发Matplotlib错误,需要提前处理。

修改后的代码示例

调整server中的绘图函数,改用显式创建Figure和Axes的方式,确保返回正确的对象:

def server(input, output, session):
  @reactive.Calc
  def random_data():
    return np.random.rand(input.nr_of_observations())
  
  @output
  @render.plot
  def my_scatter():
    # 显式创建Figure和Axes,避免全局状态干扰
    fig, ax = plt.subplots()
    ax.scatter(random_data(), random_data())
    return fig
  
  @output
  @render.plot
  def my_histogram():
    data = random_data()
    fig, ax = plt.subplots()
    # 处理空数据情况
    if len(data) > 0:
      ax.hist(data)
    else:
      ax.text(0.5, 0.5, "No data to display", ha="center", va="center")
    return fig

  @output
  @render.text
  def my_summary():
    return random_data()

内容的提问来源于stack exchange,提问作者Sebastian Gerdes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 13:20:40