1

I am trying to have user defined input to control sunburst plots. This is all coded in Python, and used both the Shiny and Plotly package. The reason for using these over dash is as I have worked with both of these in R, however this project is required to be in Python.

The idea is that, using numeric inputs, a user can edit the parameters that feed into a sunburst plot. There will be multiple inputs, but the code below applies to just a single value, as I assume that any answer will be scalable.

import plotly.graph_objs as go
import plotly.express as px
from shiny import App, reactive, render, ui,  Inputs, Outputs, Session
from shinywidgets import output_widget, register_widget
import pandas as pd



def panel_box(*args, **kwargs):
    return ui.div(
        ui.div(*args, class_="card-body"),
        **kwargs,
        class_="card mb-3",
    )

app_ui = ui.page_fluid(
    {"class": "p-4"},
    ui.row(
        ui.column(
            4,
            panel_box(
                ui.input_numeric("FirstValue", "FirstValue", min = 0, value=2),

            ),
        ),
        ui.column(
            8,
            output_widget("scatterplot"),
        ),
    ),
)

def server(input: Inputs, output: Outputs, session: Session):
    
    FirstValue = reactive.Value(2)

    @reactive.Effect
    @reactive.event(input.FirstValue)
    def _():
        FirstValue.set(input.FirstValue())

    scatterplot = go.FigureWidget(
        data=[
            go.Sunburst(
                labels = ["Eve", "Cain", "Seth", "Enos", "Noam", "Abel", "Awan", "Enoch", "Azura"],
                parents = ["", "Eve", "Eve", "Seth", "Seth", "Eve", "Eve", "Awan", "Eve" ],
                values = [2, 14, 12, 10, 2, 6, 6, 4, 4],

            ),
        ],
        layout={"showlegend": False},
    )

    @reactive.Effect
    def _():
        scatterplot.data[0].values = [FirstValue, 14, 12, 10, 2, 6, 6, 4, 4]

    register_widget("scatterplot", scatterplot)


app = App(app_ui, server)

This currently comes up with the error Error in Effect: <shiny.reactive._reactives.Value object at 0x000002275FC35540> is not JSON serializable.

I've tried several other approaches, many of which break the reactive property - this is the closest I have gotten.

How can I make the plot linked to the values the user defines?

smartse
  • 1,026
  • 7
  • 12
Beavis
  • 476
  • 3
  • 13
  • This is automatically part of the R collective. It should not be. If I need to change the tags to make it so, please let me know. – Beavis Aug 18 '23 at 14:01
  • It's because shiny is just for Rshiny. I've suggested an edit. – smartse Aug 18 '23 at 15:54

1 Answers1

0

I think the error is coming from trying to set the scatterplot data using the FirstValue object instead of its value.

I have very little experience with shiny, but looking through the documentation, you may be able to do away with the reactive event, and directly use @output and @render_widget decorators to create the plotly figure using the specified input.

import plotly.graph_objs as go
import plotly.express as px
from shiny import App, reactive, render, ui,  Inputs, Outputs, Session
from shinywidgets import output_widget, render_widget, register_widget
import pandas as pd



def panel_box(*args, **kwargs):
    return ui.div(
        ui.div(*args, class_="card-body"),
        **kwargs,
        class_="card mb-3",
    )

app_ui = ui.page_fluid(
    {"class": "p-4"},
    ui.row(
        ui.column(
            4,
            panel_box(
                ui.input_numeric("FirstValue", "FirstValue", min = 0, value=2),

            ),
        ),
        ui.column(
            8,
            output_widget("my_widget"),
        ),
    ),
)

def server(input: Inputs, output: Outputs, session: Session):
    
    @output
    @render_widget
    def my_widget():
        fig = go.FigureWidget(
            data=[
                go.Sunburst(
                    labels = ["Eve", "Cain", "Seth", "Enos", "Noam", "Abel", "Awan", "Enoch", "Azura"],
                    parents = ["", "Eve", "Eve", "Seth", "Seth", "Eve", "Eve", "Awan", "Eve" ],
                    values = [input.FirstValue(), 14, 12, 10, 2, 6, 6, 4, 4],

                ),
            ],
            layout={"showlegend": False},
        )
        return fig

app = App(app_ui, server)
app.run()

enter image description here

Derek O
  • 16,770
  • 4
  • 24
  • 43