|
| 1 | +""" pyplots.ai |
| 2 | +area-stacked-percent: 100% Stacked Area Chart |
| 3 | +Library: altair 6.0.0 | Python 3.13.11 |
| 4 | +Quality: 92/100 | Created: 2025-12-30 |
| 5 | +""" |
| 6 | + |
| 7 | +import altair as alt |
| 8 | +import numpy as np |
| 9 | +import pandas as pd |
| 10 | + |
| 11 | + |
| 12 | +# Data - Energy source mix evolution (percentage of total) |
| 13 | +np.random.seed(42) |
| 14 | +years = list(range(2015, 2025)) |
| 15 | + |
| 16 | +# Start with base percentages and evolve them (showing transition from fossil to renewables) |
| 17 | +coal = [45, 42, 39, 35, 32, 28, 25, 22, 19, 16] |
| 18 | +natural_gas = [25, 26, 27, 28, 29, 30, 31, 31, 30, 28] |
| 19 | +nuclear = [12, 12, 12, 12, 12, 12, 12, 12, 12, 12] |
| 20 | +renewables = [18, 20, 22, 25, 27, 30, 32, 35, 39, 44] |
| 21 | + |
| 22 | +# Create DataFrame in long format for Altair |
| 23 | +data = [] |
| 24 | +for i, year in enumerate(years): |
| 25 | + data.append({"Year": year, "Source": "Coal", "Percentage": coal[i]}) |
| 26 | + data.append({"Year": year, "Source": "Natural Gas", "Percentage": natural_gas[i]}) |
| 27 | + data.append({"Year": year, "Source": "Nuclear", "Percentage": nuclear[i]}) |
| 28 | + data.append({"Year": year, "Source": "Renewables", "Percentage": renewables[i]}) |
| 29 | + |
| 30 | +df = pd.DataFrame(data) |
| 31 | + |
| 32 | +# Define category order for stacking (bottom to top) using numeric order |
| 33 | +source_order = ["Coal", "Natural Gas", "Nuclear", "Renewables"] |
| 34 | +stack_order = {"Coal": 1, "Natural Gas": 2, "Nuclear": 3, "Renewables": 4} |
| 35 | +df["StackOrder"] = df["Source"].map(stack_order) |
| 36 | + |
| 37 | +# Color palette using Python colors and complementary |
| 38 | +colors = ["#306998", "#FFD43B", "#7B68EE", "#2E8B57"] |
| 39 | + |
| 40 | +# Plot - 100% Stacked Area Chart |
| 41 | +chart = ( |
| 42 | + alt.Chart(df) |
| 43 | + .mark_area(opacity=0.85, line=alt.MarkConfig(strokeWidth=2)) |
| 44 | + .encode( |
| 45 | + x=alt.X("Year:O", title="Year", axis=alt.Axis(labelFontSize=18, titleFontSize=22, labelAngle=0)), |
| 46 | + y=alt.Y( |
| 47 | + "Percentage:Q", |
| 48 | + title="Share of Energy Mix (%)", |
| 49 | + stack="normalize", |
| 50 | + axis=alt.Axis(labelFontSize=18, titleFontSize=22, format=".0%"), |
| 51 | + ), |
| 52 | + color=alt.Color( |
| 53 | + "Source:N", |
| 54 | + scale=alt.Scale(domain=source_order, range=colors), |
| 55 | + legend=alt.Legend( |
| 56 | + title="Energy Source", |
| 57 | + titleFontSize=20, |
| 58 | + labelFontSize=18, |
| 59 | + orient="right", |
| 60 | + symbolSize=300, |
| 61 | + symbolStrokeWidth=0, |
| 62 | + ), |
| 63 | + ), |
| 64 | + order=alt.Order("StackOrder:Q", sort="ascending"), |
| 65 | + tooltip=[ |
| 66 | + alt.Tooltip("Year:O", title="Year"), |
| 67 | + alt.Tooltip("Source:N", title="Source"), |
| 68 | + alt.Tooltip("Percentage:Q", title="Share", format=".1f"), |
| 69 | + ], |
| 70 | + ) |
| 71 | + .properties( |
| 72 | + width=1400, |
| 73 | + height=800, |
| 74 | + title=alt.Title(text="area-stacked-percent · altair · pyplots.ai", fontSize=28, anchor="middle"), |
| 75 | + ) |
| 76 | + .configure_axis(grid=True, gridOpacity=0.3, gridDash=[4, 4]) |
| 77 | + .configure_view(strokeWidth=0) |
| 78 | +) |
| 79 | + |
| 80 | +# Save |
| 81 | +chart.save("plot.png", scale_factor=3.0) |
| 82 | +chart.interactive().save("plot.html") |
0 commit comments