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

如何在Shiny Web应用中同时展示绘图与DataFrame表格?

解决Shiny应用同时展示绘图与数据框的问题

问题描述

我正在开发首个Shiny Web应用,通过用户输入的文本执行MySQL查询,从SQL数据库中获取数据。为简洁起见,我在代码片段中移除了查询语句。获取的数据将用于创建pandas数据框df_meetdata和绘图fig。当前应用仅能显示绘图,无法显示数据框,原因是Shiny无法从单个函数返回多个变量。请问如何才能同时展示绘图与数据框?

现有代码

app_ui = ui.page_fluid(
    ui.layout_sidebar(
        ui.panel_sidebar(
            ui.input_slider("n", "N", 0, 100, 20),
            ui.input_text("txt", "Referentienummer", value=""),
            ui.input_action_button("run", "Run"),
            ui.input_action_button("clear", "Clear"),
            ui.input_action_button("export", "Export")
        ),
        ui.panel_main(
            ui.output_text("nmr"),
            ui.output_text("print_referentienummer"),
            ui.output_plot("get_absorptie_spectrum"),
            ui.output_table("table_model"),
        ),
    ),
)


def server(input, output, session):
    @output
    @render.text
    def nmr():
        return f"input = {input.n()}"

    @output
    @render.text
    def print_referentienummer():
        return f"Referentienummer = {input.txt()}"

    @output
    @render.plot
    @reactive.event(input.run, ignore_none=True)
    def get_absorptie_spectrum():
        # Ophalen datum meting + sensorID om absorptiewaarden uit de mysql db te kunnen halen
        referentienummer = input.txt()
        
        #SQL queries for retrieving the data#

        df_meetdata = pd.DataFrame(
           {"BlueBox": bluebox_naam, "Referentienummer": referentienummer, "Datum": date_time,
            "ABS >= 2": max_absorptie}, index=[0])

        fig, ax = plt.subplots()
        ax.plot(golflengte, absorptie_waarden)
        ax.set_title(referentienummer)

        return fig

解决方案

核心思路是把数据查询和处理逻辑抽离成响应式变量,让绘图和表格输出都依赖这个变量,避免单个函数返回多个值的问题。具体步骤如下:

  • 创建响应式计算函数,统一处理SQL查询、数据框生成和绘图创建,返回包含两者的结果集合
  • 为绘图和表格分别编写独立的输出函数,从响应式变量中提取对应内容

修改后的完整代码

import pandas as pd
import matplotlib.pyplot as plt
from shiny import ui, render, reactive, App

app_ui = ui.page_fluid(
    ui.layout_sidebar(
        ui.panel_sidebar(
            ui.input_slider("n", "N", 0, 100, 20),
            ui.input_text("txt", "Referentienummer", value=""),
            ui.input_action_button("run", "Run"),
            ui.input_action_button("clear", "Clear"),
            ui.input_action_button("export", "Export")
        ),
        ui.panel_main(
            ui.output_text("nmr"),
            ui.output_text("print_referentienummer"),
            ui.output_plot("get_absorptie_spectrum"),
            ui.output_table("table_model"),
        ),
    ),
)


def server(input, output, session):
    @output
    @render.text
    def nmr():
        return f"input = {input.n()}"

    @output
    @render.text
    def print_referentienummer():
        return f"Referentienummer = {input.txt()}"

    # 统一处理数据查询与绘图生成的响应式函数
    @reactive.calc
    @reactive.event(input.run, ignore_none=True)
    def processed_data():
        referentienummer = input.txt()
        
        # 此处替换为你的实际SQL查询逻辑,获取所需变量
        bluebox_naam = "TestBox"
        date_time = "2024-05-20"
        max_absorptie = 2.5
        golflengte = [100, 200, 300]
        absorptie_waarden = [0.5, 1.2, 2.5]
        
        df_meetdata = pd.DataFrame(
           {"BlueBox": bluebox_naam, "Referentienummer": referentienummer, "Datum": date_time,
            "ABS >= 2": max_absorptie}, index=[0])

        fig, ax = plt.subplots()
        ax.plot(golflengte, absorptie_waarden)
        ax.set_title(referentienummer)
        
        # 返回包含数据框和绘图的字典
        return {"df": df_meetdata, "fig": fig}

    # 绘图输出:从响应式变量中提取绘图对象
    @output
    @render.plot
    def get_absorptie_spectrum():
        return processed_data()["fig"]

    # 表格输出:从响应式变量中提取数据框
    @output
    @render.table
    def table_model():
        return processed_data()["df"]

    # 清空按钮逻辑:重置输入框
    @reactive.Effect
    @reactive.event(input.clear)
    def _clear():
        ui.update_text("txt", value="")

app = App(app_ui, server)

关键说明

  • 响应式变量优势:processed_data()仅在点击"Run"时执行一次,避免重复查询数据库,提升应用性能;绘图和表格共享同一数据源,保证数据一致性
  • 输出拆分:每个输出对应独立的@output函数,完全符合Shiny的输出规则,解决单个函数无法返回多个值的问题
  • 扩展性:后续若需添加导出功能,可直接从processed_data()中获取数据框进行处理

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 13:52:03