-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcomposition.py
60 lines (48 loc) · 2.05 KB
/
composition.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
from shiny import reactive, ui, render, module
import matplotlib.pyplot as plt
import pandas as pd
import tempfile
def plot(data: pd.DataFrame, reference: str, comparison: str):
fractions = data.groupby([reference, comparison], observed=False).size().unstack()
fractions = fractions.div(fractions.sum(axis=1), axis=0)
fig, ax = plt.subplots()
fractions.plot.barh(stacked=True, title=f"Dataset composition ({comparison.capitalize()})", color=plt.cm.tab20.colors, ax=ax)
plt.legend(bbox_to_anchor=(1, 1.03), loc="upper left")
return fig
@module.ui
def composition_ui():
return ui.layout_sidebar(
ui.sidebar(
ui.output_ui("selectors"),
ui.download_button("download", "Download plot")
),
ui.output_plot("plot_composition")
)
@module.server
def composition_server(input, output, session, _dataframe):
_category_columns = reactive.value([])
_plot = reactive.value(None)
@reactive.effect
def update_category_columns():
_category_columns.set(_dataframe.get().select_dtypes(include="category").columns.to_list())
@output
@render.ui
def selectors():
category_columns = _category_columns.get()
return ui.input_select("reference", "Reference", choices=category_columns, selected=category_columns[0]), \
ui.input_select("comparison", "Comparison", choices=category_columns, selected=category_columns[1])
@reactive.effect
def update_plot():
_plot.set(plot(_dataframe.get(), input["reference"].get(), input["comparison"].get()))
@output
@render.plot
def plot_composition():
return _plot.get()
@output
@render.download(
filename=lambda: f"composition_{input['reference'].get()}_{input['comparison'].get()}.png"
)
def download():
with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as temp:
_plot.get().savefig(temp.name, bbox_inches="tight")
return temp.name