Having trouble creating subplots with multiple plot types

Hi @jarelan

I did not fully understand how or why you wanted to use subplots so I changed your layout. Basically each figure is separated from each other. As you are using dash anyway I thought, I could do this :see_no_evil:

from dash import Dash, dcc, html, Output, Input
from plotly import graph_objects as go
import dash_bootstrap_components as dbc
import pandas as pd

pd.set_option('display.max_rows', None)

Dash(assets_ignore='.*ignored.*')

app = Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])

# neglect false warnings
pd.options.mode.chained_assignment = None  # default='warn'

# color dictionary
class RangeDict(dict):
    def __getitem__(self, item):
        if not isinstance(item, range):
            for key in self:
                if item in key:
                    return self[key]
            raise KeyError(item)
        else:
            return super().__getitem__(item)

grade_colors = RangeDict({
    range(0, 60): 'crimson',
    range(60, 70): '#E34363',
    range(70, 80): '#FFB733',
    range(80, 90): '#29CC92',
    range(90, 101): '#339933'})

colors = {
    'background': '#111111',
    'text': 'teal',
    "0": "silver",
    "1": "#FBEC5D",
    "5": "#50C878",
    "10": "#40E0D0",
    "15": "#A23D60",
    0: "silver",
    1: "#FBEC5D",
    5: "#50C878",
    10: "#40E0D0",
    15: "#A23D60",
    'Linux': '#50C878',
    'Windows': '#66D3F4',
    'Primer': '#FFD700',
}

# pandas dataframe used for plots

students_category_earned = pd.DataFrame({
    'Category': ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'A', 'A', 'B', 'B', 'C', 'C'],
    'completed': [55, 55, 100, 95, 45, 99, 75, 64, 93, 10, 15, 55, 45, 78, 98, 33],
    'platform': ['primer', 'primer', 'primer', 'primer', 'primer', 'primer', 'primer', 'primer',
                 'primer', 'primer', 'Linux', 'Windows', 'Linux', 'Windows', 'Linux', 'Windows']
})

print(students_category_earned)
print(" - " * 9)
print(students_category_earned)

students_topics_earned = pd.DataFrame({
    'topic': ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'A', 'A', 'B', 'B', 'C', 'C'],
    'completed': [55, 55, 100, 95, 45, 99, 75, 64, 93, 10, 15, 55, 45, 78, 98, 33],
    'platform': ['primer', 'primer', 'primer', 'primer', 'primer', 'primer', 'primer', 'primer',
                 'primer', 'primer', 'Linux', 'Windows', 'Linux', 'Windows', 'Linux', 'Windows']
})

print("students_topics_earned")
print("-" * 9)
print(students_topics_earned)


# functions to creating the plots
def student_category_bar_grade(df, platform):
    df_filtered = df[df['platform'] == platform].sort_values(by='Category', ascending=True)
    fig = go.Figure()
    for completed, sdf in df_filtered.groupby('completed'):
        color = grade_colors[completed]
        fig.add_trace(
            go.Bar(
                x=sdf['Category'],
                y=sdf['completed'],
                customdata=sdf['platform'],
                name=str(completed) + " %",
                marker={'color': color},
                hovertemplate="<br>".join([
                    "Platform: %{customdata}",
                    "Category: %{x}"]),
            ),
        )
    # Change the bar mode
    fig.update_layout(title_text=platform)
    fig.update_layout(barmode='group',
                      plot_bgcolor=colors['background'],
                      paper_bgcolor=colors['background'],
                      font_color=colors['text']
                      )

    fig.update_layout(showlegend=False)
    fig.update_layout(
        title_x=0.5,
        title_font_size=26,
        title_font_family="Copperplate",
        title_font_color="teal",
    )
    return fig


def student_topic_scatter_polar_graph(df, platform):
    df_filtered = df[df['platform'] == platform].sort_values(by='topic', ascending=True)
    color = colors[platform]

    fig = go.Scatterpolar(
        r=df_filtered.completed,
        theta=df_filtered.topic,
        fill='toself',
        name="%s - Focused Topics" % platform,
        fillcolor=color,
        opacity=0.6,
        line=dict(color=color)
    )

    return go.Figure(fig)


# ------------------------------------------------MAIN CHANGES
# create a grid of dcc.Graph(), rows x columns
rows = 2
columns = 3
content = []
component_ids = []
for r in range(rows):
    row_content = []
    for c in range(columns):
        component_id = f'row{r}_col{c}'
        component_ids.append(component_id)
        row_content.append(
            dbc.Col(
                dbc.Card(
                    children=dcc.Graph(id=component_id),
                )
            )
        )
    dbc_rows = dbc.Row(
        id=f'row{r}',
        children=row_content
    )
    content.append(dbc_rows)

# app layout
app.layout = html.Div(
    [
        html.H4("Student Name"),
        dbc.Container(
            id='container',
            children=content,
            fluid=True
        ),
        # dummy component for callback triggering at startup
        html.Div(id='dummy')
    ]
)


@app.callback(
    [Output(f'{cid}', 'figure') for cid in component_ids],
    Input('dummy', 'children')
)
def update(_):
    # calling the plot functions
    linux_category_bar_fig = student_category_bar_grade(students_category_earned, 'Linux')
    windows_category_bar_fig = student_category_bar_grade(students_category_earned, 'Windows')
    primer_category_bar_fig = student_category_bar_grade(students_category_earned, 'Primer')

    linux_topic_scatter_polar_fig = student_topic_scatter_polar_graph(students_topics_earned,
                                                                      'Linux')
    windows_topic_scatter_polar_fig = student_topic_scatter_polar_graph(students_topics_earned,
                                                                        'Windows')
    primer_topic_scatter_polar_fig = student_topic_scatter_polar_graph(students_topics_earned,
                                                                       'Primer')
    return [
        linux_topic_scatter_polar_fig,
        windows_topic_scatter_polar_fig,
        primer_topic_scatter_polar_fig,
        linux_category_bar_fig,
        windows_category_bar_fig,
        primer_category_bar_fig
    ]


if __name__ == '__main__':
    app.run_server(host="0.0.0.0", port=8070, debug=True)

which creates:

1 Like