Py.Cafe

maartenbreddels/

shiny-mtcars-plotnine

mtcars Interactive Plotting with Shiny and Plotnine

DocsPricing
  • app.py
  • requirements.txt
app.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
from pathlib import Path

import pandas as pd
from plotnine import aes, facet_grid, geom_point, ggplot
from shiny import App, render, ui
from shiny.plotutils import brushed_points, near_points

mtcars = pd.read_csv(Path(__file__).parent / "mtcars.csv")
mtcars.drop(["disp", "hp", "drat", "qsec", "vs", "gear", "carb"], axis=1, inplace=True)

# In fast mode, throttle interval in ms.
FAST_INTERACT_INTERVAL = 60

app_ui = ui.page_fluid(
    ui.head_content(
        ui.tags.style(
            """
        pre, table.table {
            font-size: smaller;
        }
        """
        )
    ),
    ui.row(
        ui.column(
            4,
            ui.panel_well(
                ui.input_checkbox("facet", "Use facets", False),
                ui.input_radio_buttons(
                    "brush_dir", "Brush direction", ["xy", "x", "y"], inline=True
                ),
                ui.input_checkbox(
                    "fast",
                    f"Fast hovering/brushing (throttled with {FAST_INTERACT_INTERVAL}ms interval)",
                ),
                ui.input_checkbox("all_rows", "Return all rows in data frame", False),
                ui.input_slider(
                    "max_distance", "Max distance of point from hover", 1, 20, 5
                ),
            ),
        ),
        ui.column(
            8,
            ui.output_ui("plot_ui"),
        ),
    ),
    ui.row(
        ui.column(6, ui.tags.b("Points near cursor"), ui.output_table("near_hover")),
        ui.column(6, ui.tags.b("Points in brush"), ui.output_table("in_brush")),
    ),
)


def server(input, output, session):
    @render.ui
    def plot_ui():
        hover_opts_kwargs = {}
        brush_opts_kwargs = {}
        brush_opts_kwargs["direction"] = input.brush_dir()

        if input.fast():
            hover_opts_kwargs["delay"] = FAST_INTERACT_INTERVAL
            hover_opts_kwargs["delay_type"] = "throttle"
            brush_opts_kwargs["delay"] = FAST_INTERACT_INTERVAL
            brush_opts_kwargs["delay_type"] = "throttle"

        return ui.output_plot(
            "plot1",
            hover=ui.hover_opts(**hover_opts_kwargs),
            brush=ui.brush_opts(**brush_opts_kwargs),
        )

    @render.plot()
    def plot1():
        p = ggplot(mtcars, aes("wt", "mpg")) + geom_point()
        if input.facet():
            p = p + facet_grid("am~cyl")

        return p

    @render.table()
    def near_hover():
        return near_points(
            mtcars,
            input.plot1_hover(),
            threshold=input.max_distance(),
            add_dist=True,
            all_rows=input.all_rows(),
        )

    @render.table()
    def in_brush():
        return brushed_points(
            mtcars,
            input.plot1_brush(),
            all_rows=input.all_rows(),
        )


app = App(app_ui, server)


def format_table(df: pd.DataFrame):
    return (
        df.style.set_table_attributes('class="dataframe shiny-table table w-auto"')
        .hide(axis="index")  # pyright: reportUnknownMemberType=false
        .set_table_styles(
            [
                dict(selector="th", props=[("text-align", "right")]),
                dict(
                    selector="tr>td",
                    props=[
                        ("padding-top", "0.1rem"),
                        ("padding-bottom", "0.1rem"),
                    ],
                ),
            ]  # pyright: reportGeneralTypeIssues=false
        )
    )
mtcars.csv
1
Could not load content