{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Plotting aggregate variables\n", "\n", "The **pyam** package offers many great visualisation and analysis tools. In this notebook, we highlight the `aggregate` and `stack_plot` methods of an `IamDataFrame`. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%matplotlib inline" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Aggregating sectors\n", "\n", "Here we provide some sample data for the first part of this tutorial. This data is for a single model-scenario-region combination but provides multiple subsectors of CO$_2$ emissions. The emissions in the subsectors are both positive and negative and so provide a good test of the flexibility of our aggregation and plotting routines." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import pandas as pd\n", "\n", "from pyam import IamDataFrame\n", "\n", "df = IamDataFrame(\n", " pd.DataFrame(\n", " [\n", " [\n", " \"IMG\",\n", " \"a_scen\",\n", " \"World\",\n", " \"Emissions|CO2|Energy|Oil\",\n", " \"Mt CO2/yr\",\n", " 2,\n", " 3.2,\n", " 2.0,\n", " 1.8,\n", " ],\n", " [\n", " \"IMG\",\n", " \"a_scen\",\n", " \"World\",\n", " \"Emissions|CO2|Energy|Gas\",\n", " \"Mt CO2/yr\",\n", " 1.3,\n", " 1.6,\n", " 1.0,\n", " 0.7,\n", " ],\n", " [\n", " \"IMG\",\n", " \"a_scen\",\n", " \"World\",\n", " \"Emissions|CO2|Energy|BECCS\",\n", " \"Mt CO2/yr\",\n", " 0.0,\n", " 0.4,\n", " -0.4,\n", " 0.3,\n", " ],\n", " [\n", " \"IMG\",\n", " \"a_scen\",\n", " \"World\",\n", " \"Emissions|CO2|Cars\",\n", " \"Mt CO2/yr\",\n", " 1.6,\n", " 3.8,\n", " 3.0,\n", " 2.5,\n", " ],\n", " [\n", " \"IMG\",\n", " \"a_scen\",\n", " \"World\",\n", " \"Emissions|CO2|Tar\",\n", " \"Mt CO2/yr\",\n", " 0.3,\n", " 0.35,\n", " 0.35,\n", " 0.33,\n", " ],\n", " [\n", " \"IMG\",\n", " \"a_scen\",\n", " \"World\",\n", " \"Emissions|CO2|Agg\",\n", " \"Mt CO2/yr\",\n", " 0.5,\n", " -0.1,\n", " -0.5,\n", " -0.7,\n", " ],\n", " [\n", " \"IMG\",\n", " \"a_scen\",\n", " \"World\",\n", " \"Emissions|CO2|LUC\",\n", " \"Mt CO2/yr\",\n", " -0.3,\n", " -0.6,\n", " -1.2,\n", " -1.0,\n", " ],\n", " ],\n", " columns=[\n", " \"model\",\n", " \"scenario\",\n", " \"region\",\n", " \"variable\",\n", " \"unit\",\n", " 2005,\n", " 2010,\n", " 2015,\n", " 2020,\n", " ],\n", " )\n", ")\n", "df.head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Pyam's `stackplot` method plots the stacks in the clearest way possible, even when some emissions are negative. The optional `total` keyword arguments also allows the user to include a total line on their plot." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df.plot.stack()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df.plot.stack(total=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The appearance of the stackplot can be simply controlled via ``kwargs``. The appearance of the total line is controlled by passing a dictionary to the `total_kwargs` keyword argument." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df.plot.stack(alpha=0.5, total={\"color\": \"grey\", \"ls\": \"--\", \"lw\": 2.0})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If the user wishes, they can firstly filter their data before plotting." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df.filter(variable=\"Emissions|CO2|Energy*\").plot.stack(total=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Using `aggregate`, it is possible to create arbitrary sums of sub-sectors before plotting." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "pdf = df.copy()\n", "afoluluc_vars = [\"Emissions|CO2|LUC\", \"Emissions|CO2|Agg\"]\n", "fossil_vars = list(set(pdf.variable) - set(afoluluc_vars))\n", "pdf.aggregate(\"Emissions|CO2|AFOLULUC\", components=afoluluc_vars, append=True)\n", "pdf.aggregate(\"Emissions|CO2|Fossil\", components=fossil_vars, append=True)\n", "pdf.filter(variable=[\"Emissions|CO2|AFOLULUC\", \"Emissions|CO2|Fossil\"]).plot.stack(\n", " total=True\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Aggregating regions\n", "\n", "Here we provide some sample data for the second part of this tutorial. This data is for a single model-scenario combination with a few subsectors of CO$_2$ emissions. The emissions in the subsectors are both positive and negative and so provide a good test of the flexibility of our aggregation and plotting routines." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df = IamDataFrame(\n", " pd.DataFrame(\n", " [\n", " [\n", " \"IMG\",\n", " \"a_scen\",\n", " \"World\",\n", " \"Emissions|CO2\",\n", " \"Mt CO2/yr\",\n", " 4.6,\n", " 5.3,\n", " 5.5,\n", " 4.3,\n", " ],\n", " [\n", " \"IMG\",\n", " \"a_scen\",\n", " \"World\",\n", " \"Emissions|CO2|Fossil\",\n", " \"Mt CO2/yr\",\n", " 4.0,\n", " 4.6,\n", " 4.9,\n", " 4.1,\n", " ],\n", " [\n", " \"IMG\",\n", " \"a_scen\",\n", " \"World\",\n", " \"Emissions|CO2|AFOLU\",\n", " \"Mt CO2/yr\",\n", " 0.6,\n", " 0.7,\n", " 0.6,\n", " 0.2,\n", " ],\n", " [\n", " \"IMG\",\n", " \"a_scen\",\n", " \"World\",\n", " \"Emissions|CO2|Fossil|Energy\",\n", " \"Mt CO2/yr\",\n", " 3.6,\n", " 4.1,\n", " 4.3,\n", " 3.6,\n", " ],\n", " [\n", " \"IMG\",\n", " \"a_scen\",\n", " \"World\",\n", " \"Emissions|CO2|Fossil|Aviation\",\n", " \"Mt CO2/yr\",\n", " 0.4,\n", " 0.5,\n", " 0.6,\n", " 0.5,\n", " ],\n", " [\n", " \"IMG\",\n", " \"a_scen\",\n", " \"R5ASIA\",\n", " \"Emissions|CO2\",\n", " \"Mt CO2/yr\",\n", " 2.3,\n", " 2.6,\n", " 2.8,\n", " 2.6,\n", " ],\n", " [\n", " \"IMG\",\n", " \"a_scen\",\n", " \"R5ASIA\",\n", " \"Emissions|CO2|Fossil\",\n", " \"Mt CO2/yr\",\n", " 2.0,\n", " 2.1,\n", " 2.2,\n", " 2.3,\n", " ],\n", " [\n", " \"IMG\",\n", " \"a_scen\",\n", " \"R5ASIA\",\n", " \"Emissions|CO2|Fossil|Energy\",\n", " \"Mt CO2/yr\",\n", " 2.0,\n", " 2.1,\n", " 2.2,\n", " 2.3,\n", " ],\n", " [\n", " \"IMG\",\n", " \"a_scen\",\n", " \"R5ASIA\",\n", " \"Emissions|CO2|AFOLU\",\n", " \"Mt CO2/yr\",\n", " 0.3,\n", " 0.5,\n", " 0.6,\n", " 0.3,\n", " ],\n", " [\n", " \"IMG\",\n", " \"a_scen\",\n", " \"R5LAM\",\n", " \"Emissions|CO2\",\n", " \"Mt CO2/yr\",\n", " 1.9,\n", " 2.2,\n", " 2.1,\n", " 1.2,\n", " ],\n", " [\n", " \"IMG\",\n", " \"a_scen\",\n", " \"R5LAM\",\n", " \"Emissions|CO2|Fossil\",\n", " \"Mt CO2/yr\",\n", " 1.6,\n", " 2.0,\n", " 2.1,\n", " 1.3,\n", " ],\n", " [\n", " \"IMG\",\n", " \"a_scen\",\n", " \"R5LAM\",\n", " \"Emissions|CO2|Fossil|Energy\",\n", " \"Mt CO2/yr\",\n", " 1.6,\n", " 2.0,\n", " 2.1,\n", " 1.3,\n", " ],\n", " [\n", " \"IMG\",\n", " \"a_scen\",\n", " \"R5LAM\",\n", " \"Emissions|CO2|AFOLU\",\n", " \"Mt CO2/yr\",\n", " 0.3,\n", " 0.2,\n", " 0,\n", " -0.1,\n", " ],\n", " ],\n", " columns=[\n", " \"model\",\n", " \"scenario\",\n", " \"region\",\n", " \"variable\",\n", " \"unit\",\n", " 2005,\n", " 2010,\n", " 2015,\n", " 2020,\n", " ],\n", " )\n", ")\n", "df.head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If we aggregate the regional values for a sector, we get back the world total." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df.aggregate_region(\"Emissions|CO2|AFOLU\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df.filter(variable=\"Emissions|CO2|AFOLU\", region=\"World\").timeseries()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can plot this as shown. The black line shows the World total (which is the same as the total lines shown in the previous part)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "\n", "ax = plt.figure(figsize=(8, 4.5)).add_subplot(111)\n", "df.filter(variable=\"Emissions|CO2|AFOLU\").filter(region=\"World\", keep=False).plot.stack(\n", " stack=\"region\", ax=ax\n", ")\n", "df.filter(variable=\"Emissions|CO2|AFOLU\", region=\"World\").plot(ax=ax, color=\"black\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Even if there are sectors which are defined only at the world level (e.g. `Emissions|CO2|Fossil|Aviation` in our example), **pyam** will find them and include them when calculating the regional total if we specify `components=True` when using `aggregate_region`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df.aggregate_region(\"Emissions|CO2|Fossil\", components=True).timeseries()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df.filter(variable=\"Emissions|CO2|Fossil\", region=\"World\").timeseries()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If we plot the regions vs. the total, in this case we will see a gap. This gap represents the emissions from variables only defined at the world level." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ax = plt.figure(figsize=(8, 4.5)).add_subplot(111)\n", "df.filter(variable=\"Emissions|CO2|Fossil\").filter(\n", " region=\"World\", keep=False\n", ").plot.stack(stack=\"region\", ax=ax)\n", "df.filter(variable=\"Emissions|CO2|Fossil\", region=\"World\").plot(ax=ax, color=\"black\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can verify this by making sure that adding the aviation emissions to the regional emissions does indeed give the aggregate total (a nicer way would be to plot these emissions in the stack above, pull requests which do so are welcome :D)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "\n", "aviation_emms = df.filter(variable=\"*Aviation*\").timeseries()\n", "aggregate_emms = df.aggregate_region(\n", " \"Emissions|CO2|Fossil\", components=True\n", ").timeseries()\n", "aggregate_emms_region_only = (\n", " df.filter(region=\"World\", keep=False)\n", " .aggregate_region(\"Emissions|CO2|Fossil\")\n", " .timeseries()\n", ")\n", "np.isclose(\n", " aggregate_emms.values, aggregate_emms_region_only.values + aviation_emms.values\n", ")" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.0" } }, "nbformat": 4, "nbformat_minor": 2 }