|
10 | 10 | "This notebook contains example data processing using the output of an example\n", |
11 | 11 | "model.\n", |
12 | 12 | "\n", |
13 | | - "Output files are mostly in CSV format. The format of output files is documented [here][output-format].\n", |
14 | | - "\n", |
15 | | - "We begin by loading the `model.toml` input file to get the list of milestone years.\n", |
| 13 | + "Output files are mostly in CSV format. The format of output files is documented [in MUSE2 documentation][output-format].\n", |
16 | 14 | "\n", |
17 | 15 | "[output-format]: https://energysystemsmodellinglab.github.io/MUSE2/file_formats/output_files.html" |
18 | 16 | ] |
|
24 | 22 | "metadata": {}, |
25 | 23 | "outputs": [], |
26 | 24 | "source": [ |
27 | | - "import tomllib\n", |
28 | | - "\n", |
29 | 25 | "import pandas as pd\n", |
30 | 26 | "\n", |
31 | | - "from muse2_data_analysis.helpers import get_example_input_dir, get_example_output_dir\n", |
32 | | - "\n", |
33 | | - "INPUT_DIR = get_example_input_dir()\n", |
34 | | - "OUTPUT_DIR = get_example_output_dir()\n", |
| 27 | + "from muse2_data_analysis.helpers import get_example_output_dir\n", |
35 | 28 | "\n", |
36 | | - "with (INPUT_DIR / \"model.toml\").open(\"rb\") as f:\n", |
37 | | - " model = tomllib.load(f)\n", |
38 | | - "\n", |
39 | | - "# We need to know the milestone years for processing the assets file\n", |
40 | | - "years = model[\"milestone_years\"]" |
| 29 | + "OUTPUT_DIR = get_example_output_dir()" |
41 | 30 | ] |
42 | 31 | }, |
43 | 32 | { |
|
48 | 37 | "## Load and process output data\n", |
49 | 38 | "\n", |
50 | 39 | "We next load the output data. In this case, we want to calculate how much capacity was invested in\n", |
51 | | - "different processes for different agents. This information can be found in the `assets.csv` output\n", |
52 | | - "file.\n", |
| 40 | + "different processes for different agents. This information can be found in the `asset_capacities.csv`\n", |
| 41 | + "output file.\n", |
53 | 42 | "\n", |
54 | | - "The `assets.csv` file contains information about different assets, including when they were\n", |
55 | | - "commissioned and decommissioned as well as their capacity. To calculate the overall capacity for a\n", |
56 | | - "given agent and process type, we have to process this data. Note that different assets owned by the\n", |
57 | | - "same agent may have the same process ID if the agent has reinvested in the same process type in a\n", |
58 | | - "different year." |
| 43 | + "We also need some metadata, like the agent that manages the asset and the process the asset corresponds\n", |
| 44 | + "to. That time-independent information is contained in the `assets.csv` file. To calculate the overall\n", |
| 45 | + "capacity for a given agent and process type as a function of milestone year, we have to combine these\n", |
| 46 | + "two files and process the data." |
59 | 47 | ] |
60 | 48 | }, |
61 | 49 | { |
|
65 | 53 | "metadata": {}, |
66 | 54 | "outputs": [], |
67 | 55 | "source": [ |
68 | | - "# The assets.csv file contains info about which assets were invested in and when\n", |
69 | 56 | "assets = pd.read_csv(OUTPUT_DIR / \"assets.csv\")\n", |
70 | | - "\n", |
71 | | - "# Assets with no decommission_year are effectively decommissioned after time horizon\n", |
72 | | - "assets[\"decommission_year\"] = assets[\"decommission_year\"].fillna(years[-1] + 1)\n", |
73 | | - "\n", |
74 | | - "# Calculate capacity for each type of process for each agent\n", |
75 | | - "capacity = pd.DataFrame()\n", |
76 | | - "for year in years:\n", |
77 | | - " active = assets[\n", |
78 | | - " (year >= assets[\"commission_year\"]) & (year < assets[\"decommission_year\"])\n", |
79 | | - " ]\n", |
80 | | - "\n", |
81 | | - " # This only works because each agent is responsible for one and only one commodity\n", |
82 | | - " cap_sum = active.groupby([\"agent_id\", \"process_id\"])[\"capacity\"].sum().reset_index()\n", |
83 | | - "\n", |
84 | | - " df = pd.DataFrame(cap_sum)\n", |
85 | | - " df[\"year\"] = year\n", |
86 | | - "\n", |
87 | | - " capacity = pd.concat([capacity, df])\n", |
88 | | - "\n", |
89 | | - "capacity" |
| 57 | + "asset_capacities = pd.read_csv(OUTPUT_DIR / \"asset_capacities.csv\")\n", |
| 58 | + "\n", |
| 59 | + "merged = asset_capacities.merge(assets, on=[\"asset_id\", \"group_id\"])\n", |
| 60 | + "agg_capacities = merged.groupby([\"milestone_year\", \"agent_id\", \"process_id\"])[\n", |
| 61 | + " \"capacity\"\n", |
| 62 | + "].sum()\n", |
| 63 | + "agg_capacities_wide = agg_capacities.unstack([\"agent_id\", \"process_id\"], fill_value=0)\n", |
| 64 | + "agg_capacities_wide" |
90 | 65 | ] |
91 | 66 | }, |
92 | 67 | { |
|
96 | 71 | "source": [ |
97 | 72 | "## Plot results\n", |
98 | 73 | "\n", |
99 | | - "Finally, we plot the results.\n", |
100 | | - "\n", |
101 | | - "Note that each of the agents has invested in only one process type; otherwise there would be\n", |
102 | | - "multiple bars per plot here." |
| 74 | + "Finally, we plot the results." |
103 | 75 | ] |
104 | 76 | }, |
105 | 77 | { |
|
111 | 83 | "source": [ |
112 | 84 | "import matplotlib.pyplot as plt\n", |
113 | 85 | "\n", |
114 | | - "agents = capacity[\"agent_id\"].unique()\n", |
115 | | - "_, axes = plt.subplots(1, len(agents))\n", |
| 86 | + "agents = agg_capacities_wide.columns.get_level_values(\"agent_id\").unique()\n", |
| 87 | + "fig, axes = plt.subplots(1, len(agents), figsize=(4 * len(agents), 4))\n", |
116 | 88 | "for ax, agent in zip(axes, agents):\n", |
117 | | - " capacity[capacity[\"agent_id\"] == agent].pivot(\n", |
118 | | - " index=\"year\", columns=\"process_id\", values=\"capacity\"\n", |
119 | | - " ).plot(kind=\"bar\", ax=ax)\n", |
120 | | - " ax.set_title(agent)\n", |
121 | | - " ax.set_xlabel(\"Year\")\n", |
122 | | - " ax.set_ylabel(\"Capacity\")\n", |
123 | | - " ax.legend(title=\"Process\")" |
| 89 | + " agg_capacities_wide[agent].plot(\n", |
| 90 | + " kind=\"bar\", stacked=True, ax=ax, title=agent, xlabel=\"Year\", ylabel=\"Capacity\"\n", |
| 91 | + " )\n", |
| 92 | + "\n", |
| 93 | + "plt.tight_layout()" |
124 | 94 | ] |
125 | 95 | } |
126 | 96 | ], |
127 | 97 | "metadata": { |
128 | 98 | "kernelspec": { |
129 | | - "display_name": "muse2-data-analysis", |
| 99 | + "display_name": "Python 3 (ipykernel)", |
130 | 100 | "language": "python", |
131 | 101 | "name": "python3" |
132 | 102 | }, |
|
140 | 110 | "name": "python", |
141 | 111 | "nbconvert_exporter": "python", |
142 | 112 | "pygments_lexer": "ipython3", |
143 | | - "version": "3.14.2" |
| 113 | + "version": "3.14.6" |
144 | 114 | } |
145 | 115 | }, |
146 | 116 | "nbformat": 4, |
|
0 commit comments