posit-dev / py-shinywidgets

Render ipywidgets inside a PyShiny app
MIT License
41 stars 2 forks source link

Can't plot altair concatenated plots #123

Closed stephenwilliams22 closed 7 months ago

stephenwilliams22 commented 7 months ago

Description

I'm tying to display concatenated altair plots in shiny-python using a mofied version of your altair example from https://github.com/posit-dev/py-shinywidgets/blob/5a6f7f0535732b2b18bb1bdd0c1ea088df9c9dd7/examples/altair/app.py#L2

What I Did

import altair as alt
import pandas as pd
from shiny import App, render, ui
from shinywidgets import output_widget, reactive_read, register_widget
from vega_datasets import data

source = data.cars()

app_ui = ui.page_fluid(ui.output_text_verbatim("selection"), output_widget("chart"))

def server(input, output, session):

    # Replicate JupyterChart interactivity
    # https://altair-viz.github.io/user_guide/jupyter_chart.html#point-selections
    brush = alt.selection_point(name="point", encodings=["color"], bind="legend")
    chart = (
        alt.Chart(source)
        .mark_point()
        .encode(
            x="Horsepower:Q",
            y="Miles_per_Gallon:Q",
            color=alt.condition(brush, "Origin:N", alt.value("grey")),
        )
        .add_params(brush)
    )

    chart1 = (
        alt.Chart(source)
        .mark_point()
        .encode(
            x="Horsepower:Q",
            y="Miles_per_Gallon:Q",
            color=alt.condition(brush, "Origin:N", alt.value("grey")),
        )
        .add_params(brush)
    )
    charts = alt.concat(chart, chart1)
    jchart = alt.JupyterChart(charts)

    # Display/register the chart in the app_ui
    register_widget("chart", jchart)

    # Reactive-ly read point selections
    @output
    @render.text
    def selection():
        pt = reactive_read(jchart.selections, "point")
        return "Selected point: " + str(pt)

app = App(app_ui, server)
/external/anaconda/lib/python3.10/site-packages/altair/utils/schemapi.py", line 983, in to_dict
    raise SchemaValidationError(self, err) from None
altair.utils.schemapi.SchemaValidationError: `ConcatChart` has no parameter named 'height'

Existing parameter names are:
vconcat      center     description   params    title       
autosize     config     name          resolve   transform   
background   data       padding       spacing   usermeta    
bounds       datasets                                       

See the help for `ConcatChart` to read the full description of these parameters
cpsievert commented 7 months ago

Thanks for the report, closed via #125.

By the way, if filling layout is important, you'll want to use shiny.ui.layout_column_wrap() over altair.concat() since the former can support filling layouts.

import altair as alt
import pandas as pd
from shiny import App, render, ui
from vega_datasets import data

from shinywidgets import output_widget, register_widget

source = data.cars()

app_ui = ui.page_fillable(
    ui.layout_column_wrap(
        output_widget("chart1"),
        output_widget("chart2"),
        width=1 / 2
    )
)

def server(input, output, session):

    brush = alt.selection_point(name="point", encodings=["color"], bind="legend")
    chart1 = (
        alt.Chart(source)
        .mark_point()
        .encode(
            x="Horsepower:Q",
            y="Miles_per_Gallon:Q",
            color=alt.condition(brush, "Origin:N", alt.value("grey")),
        )
        .add_params(brush)
    )

    chart2 = (
        alt.Chart(source)
        .mark_point()
        .encode(
            x="Horsepower:Q",
            y="Miles_per_Gallon:Q",
            color=alt.condition(brush, "Origin:N", alt.value("grey")),
        )
        .add_params(brush)
    )

    register_widget("chart1", chart1)
    register_widget("chart2", chart2)

app = App(app_ui, server)
stephenwilliams22 commented 7 months ago

Thanks @cpsievert. Is shiny.ui.layout_column_wrap() compatible with a list of plots? I'm interested in rendering a variable number of plots. How would I go from a list of altair plots in the server being rendered in the UI?