如何在 PyShiny 中获取多个绘图?

问题描述 投票:0回答:3

我一直在尝试在 PyShiny 中重现 这个最小的 R Shiny 应用程序,但没有成功。我尝试将 R 代码字面翻译为 python 代码,但看起来我需要在

@render.plot
装饰器内动态命名plotname()函数。我所有的尝试都没有返回任何情节。我知道问题出在底部附近的 exec() 行。如何动态更改循环中的函数名称?有关修复以下代码的任何帮助:

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

#========== helper function =======================
def do_call(what, args=[], kwargs = {}): # code picked from https://stackoverflow.com/questions/38722804/equivalent-to-rs-do-call-in-python
    return what(*args, **kwargs)
#=================================================
max_plots = 5

app_ui = ui.page_fluid(
    ui.input_slider("n", "Number of plots", value=1, min=1, max=5),
    ui.output_ui("plots")
)

def server(input, output, session):
     
    @output
    @render.ui
    def plots():
        plot_output_list = []
        for i in range(1, input.n()+1):
            plotname = f"plot{i}"
            
            plot_output_list.append(ui.output_plot(plotname))
        return do_call(ui.TagList, plot_output_list)

    for j in range(1, max_plots+1):
        #my_i = j
        #plotname = f"plot{my_i}"
        @output
        @render.plot
        def exec(f"plot{j}")(): # this line is not correct
            fig = plt.plot(range(1, j+1), range(1, j+1))
            return fig

app = App(app_ui, server)
python shiny plotly-dash dashboard py-shiny
3个回答
0
投票
from shiny import App, render, ui
import matplotlib.pyplot as plt


## ========== helper function =======================##
def do_call(what, args=[],
            kwargs={}):  # code picked from https://stackoverflow.com/questions/38722804/equivalent-to-rs-do-call-in-python
    return what(*args, **kwargs)


# =================================================
max_plots = 5

app_ui = ui.page_fluid(
    ui.input_slider("n", "Number of plots", value=1, min=1, max=5),
    ui.output_ui("plots")
)


def server(input, output, session):
    @output
    @render.ui
    def plots():
        plot_output_list = []
        for i in range(1, input.n() + 1):
            plotname = f"plot{i}"

            plot_output_list.append(ui.output_plot(plotname))
        return do_call(ui.TagList, plot_output_list)

    for j in range(1, max_plots + 1):
        @output(f"plot{j}")
        @render.plot
        def exec():
            fig = plt.plot(range(1, j + 1), range(1, j + 1))
            return fig

app = App(app_ui, server)

0
投票

我终于找到了一个有效的解决方案。我正在发布解决方案,以防其他人需要它。


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


#========== helper function =======================
def do_call(what, args=[], kwargs = {}): # code picked from https://stackoverflow.com/questions/38722804/equivalent-to-rs-do-call-in-python
    return what(*args, **kwargs)
#=================================================
max_plots = 5

app_ui = ui.page_fluid(
    ui.input_slider("n", "Number of plots", value=1, min=1, max=5),
    ui.output_ui("plots")
)

def server(input, output, session):
     
    @output
    @render.ui
    def plots():
        plot_output_list = []
        for i in range(1, input.n()+1):
            plotname = f"plot{i}"
            
            plot_output_list.append(ui.output_plot(plotname))
        return do_call(ui.TagList, plot_output_list)

    for j in range(1, max_plots+1):
        exec(f"@output\[email protected]\ndef plot{j}():\n    fig = plt.plot(range(1, {j+1}), range(1, {j+1}))\n    return fig")

app = App(app_ui, server)

0
投票

该解决方案正确捕获了每个图的上下文(每个图都是不同的——查看坐标轴)。原始代码使用循环中定义的单个闭包,因此所有 5 个图都是相同的。

do_call
助手是不必要的——只需调用
ui.tagList()

请注意,您也可以直接在

render.plot
中调用
render_plot_func
,而不是使用装饰器,即
return render.plot(f)
并删除
@render.plot
。在输出的情况下,您不能使用装饰器语法,因为那里没有可以注释的函数定义。

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

# =================================================
max_plots = 5

app_ui = ui.page_fluid(
    ui.input_slider("n", "Number of plots", value=1, min=1, max=5),
    ui.output_ui("plots")
)


def server(input, output, session):
    def render_plot_func(j):
        @render.plot
        def f():
            fig = plt.plot(range(1, j + 1), range(1, j + 1))
            return fig
        return f
        
    @output
    @render.ui
    def plots():
        plot_output_list = []
        for i in range(1, input.n() + 1):
            plotname = f"plot{i}"

            plot_output_list.append(ui.output_plot(plotname))
            output(render_plot_func(i), id=plotname)
        return ui.TagList(plot_output_list)

app = App(app_ui, server)

@sbik:您对自己问题的回答看起来很有效,但我建议首选此版本(没有

exec
调用),以提高可读性。

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.