Give a Distribution Chart a Stable Color Contract Before It Starts Shouting

Give a Distribution Chart a Stable Color Contract Before It Starts Shouting
Suggested cover: a dashboard panel with a donut chart using stable category colors and a small legend that reads clearly.

The distribution chart gets clearer when the palette, frame and figure are separated

The right-hand chart section carries more moving pieces than the line chart: a grouped series, a fixed color mapping, a small dataframe for Plotly and the figure configuration itself. The logic is still direct, but it reads better when those parts are split into several smaller source-faithful blocks.

This keeps the same visual recipe from the dashboard while making each stage easier to inspect and restore.

TermMeaningWhy it matters
Color mapThe explicit category-to-color dictionary.It fixes the visual identity of each vehicle group.
Pie frameThe small dataframe built for Plotly.It gives the chart clean column names and values.
Figure setupThe Plotly call plus the follow-up update methods.It defines the final visual behavior of the donut chart.

The right column opens with the grouped totals

            with col6:
                st.subheader("Distribution by Vehicle Type")
                pie_data = df.groupby('vehicle_type')['intensity'].sum()

The grouped category totals stay attached to the right chart column, but they now sit in a smaller entry block.

The palette remains a standalone contract

                colors = {
                    'car': '#4CAF50',
                    'motorcycle': '#FFC107',
                    'bus': '#2196F3',
                    'truck': '#F44336'
                }

The color dictionary becomes easier to reuse when it is isolated from the rest of the plotting code.

                import plotly.express as px
                pie_df = pd.DataFrame({
                    'Vehicle Type': pie_data.index,
                    'Count': pie_data.values
                })

The temporary dataframe now has its own block, which keeps the bridge from pandas to Plotly visible.

                fig = px.pie(
                    pie_df, 
                    values='Count', 
                    names='Vehicle Type',
                    title='Vehicle Distribution',
                    color='Vehicle Type',
                    color_discrete_map=colors,
                    hole=0.4
                )

The figure declaration keeps the same arguments from the dashboard, but it is easier to read now that it stands alone.

                fig.update_traces(textposition='inside', textinfo='percent+label')
                fig.update_layout(showlegend=True, height=400)
                st.plotly_chart(fig, use_container_width=True)

The update calls and final render now sit together as the finishing step of the right-hand chart.

  • The grouped totals, the palette, the dataframe and the figure are now easier to read as separate layers.
  • The Plotly import is preserved exactly where the dashboard introduced it.
  • The final render call remains unchanged, but it no longer competes with the palette definition in the same code slab.
A color contract is easier to preserve when the palette and the figure setup can be read as separate stages.