
pyam_analysis package¶The pyam-analysis package provides a range of diagnostic tools and functions
for analyzing and working with IAMC-style timeseries data.
The package can be used with data that follows the data template convention of the Integrated Assessment Modeling Consortium (IAMC). An illustrative example is shown below; see data.ene.iiasa.ac.at/database for more information.
| model | scenario | region | variable | unit | 2005 | 2010 | 2015 |
|---|---|---|---|---|---|---|---|
| MESSAGE V.4 | AMPERE3-Base | World | Primary Energy | EJ/y | 454.5 | 479.6 | ... |
| ... | ... | ... | ... | ... | ... | ... | ... |
First, we import the snapshot timeseries data from the file tutorial_AR5_data.csv in the tutorial folder.
As a first step, we show lists of all models, scenarios, regions, and variables (with units) included in the snapshot.
import pyam_analysis as iam
data = '/home/gidden/work/iiasa/message/pyam-analysis/tutorial/tutorial_AR5_data.csv'
df = iam.IamDataFrame(data=data)
df.models()
['AIM-Enduse 12.1', 'GCAM 3.0', 'IMAGE 2.4', 'MERGE_EMF27', 'MESSAGE V.4', 'REMIND 1.5', 'WITCH_EMF27']
df.scenarios()
['EMF27-450-Conv', 'EMF27-450-NoCCS', 'EMF27-550-LimBio', 'EMF27-Base-FullTech', 'EMF27-G8-EERE', 'AMPERE3-450', 'AMPERE3-450P-CE', 'AMPERE3-450P-EU', 'AMPERE3-550', 'AMPERE3-Base-EUback', 'AMPERE3-CF450P-EU', 'AMPERE3-RefPol', 'AMPERE3-550P-EU']
df.regions()
['ASIA', 'LAM', 'MAF', 'OECD90', 'REF', 'World']
df.variables(include_units=True)
| variable | unit | |
|---|---|---|
| 0 | Emissions|CO2 | Mt CO2/yr |
| 1 | Emissions|CO2|Fossil Fuels and Industry | Mt CO2/yr |
| 2 | Primary Energy | EJ/yr |
| 3 | Emissions|CO2|Fossil Fuels and Industry|Energy... | Mt CO2/yr |
| 4 | Emissions|CO2|Fossil Fuels and Industry|Energy... | Mt CO2/yr |
| 5 | Price|Carbon | US$2005/t CO2 |
| 6 | Primary Energy|Coal | EJ/yr |
| 7 | Primary Energy|Fossil|w/ CCS | EJ/yr |
| 8 | Temperature|Global Mean|MAGICC6|MED | deg C |
df.scenarios({'model': 'MESSAGE'})
['AMPERE3-450', 'AMPERE3-450P-EU', 'AMPERE3-550', 'AMPERE3-RefPol', 'EMF27-550-LimBio', 'EMF27-Base-FullTech']
df.scenarios({'model': 'ESSAGE'})
[]
df.variables(filters={'variable': 'Emissions|*'})
['Emissions|CO2', 'Emissions|CO2|Fossil Fuels and Industry', 'Emissions|CO2|Fossil Fuels and Industry|Energy Supply', 'Emissions|CO2|Fossil Fuels and Industry|Energy Supply|Electricity']
df.variables(filters={'variable': 'Emissions|*', 'level': 2})
['Emissions|CO2', 'Emissions|CO2|Fossil Fuels and Industry', 'Emissions|CO2|Fossil Fuels and Industry|Energy Supply']
df.variables(filters={'level': 1})
['Emissions|CO2', 'Price|Carbon', 'Primary Energy', 'Primary Energy|Coal']
df.timeseries(filters={
'scenario': 'AMPERE3-450',
'variable': 'Primary Energy|Coal',
'region': 'World'
}).head()
| year | 2005 | 2010 | 2020 | 2030 | 2040 | 2050 | 2060 | 2070 | 2080 | 2090 | 2100 | ||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| model | scenario | region | variable | unit | |||||||||||
| GCAM 3.0 | AMPERE3-450 | World | Primary Energy|Coal | EJ/yr | 120.76 | 144.95 | 176.44 | 204.42 | 212.84 | 186.02 | 138.23 | 106.98 | 82.44 | 36.55 | 14.89 |
| AMPERE3-450P-CE | World | Primary Energy|Coal | EJ/yr | 120.76 | 144.95 | 178.98 | 218.24 | 213.35 | 192.45 | 142.64 | 108.72 | 82.73 | 36.89 | 15.22 | |
| AMPERE3-450P-EU | World | Primary Energy|Coal | EJ/yr | 120.76 | 144.95 | 189.86 | 241.25 | 224.25 | 191.70 | 136.72 | 102.51 | 80.72 | 35.70 | 14.45 | |
| IMAGE 2.4 | AMPERE3-450 | World | Primary Energy|Coal | EJ/yr | 111.62 | 138.69 | 148.60 | 121.24 | 102.62 | 101.41 | 111.41 | 138.40 | 181.03 | 224.03 | 264.77 |
| AMPERE3-450P-CE | World | Primary Energy|Coal | EJ/yr | 111.62 | 138.69 | 161.72 | 154.18 | 125.14 | 105.32 | 120.83 | 151.58 | 192.67 | 249.50 | 294.40 |
df.pivot_table(
index=['year'],
columns=['scenario'],
values='value',
aggfunc='sum',
filters={'variable': 'Primary Energy', 'region': 'World'}
).head()
| scenario | AMPERE3-450 | AMPERE3-450P-CE | AMPERE3-450P-EU | AMPERE3-550 | AMPERE3-550P-EU | AMPERE3-Base-EUback | AMPERE3-CF450P-EU | AMPERE3-RefPol | EMF27-450-Conv | EMF27-450-NoCCS | EMF27-550-LimBio | EMF27-Base-FullTech | EMF27-G8-EERE |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| year | |||||||||||||
| 2005 | 1821.09 | 1366.48 | 1821.09 | 1818.71 | 464.82 | 922.58 | 925.23 | 1818.44 | 2234.35 | 1381.84 | 3130.81 | 3130.60 | 868.79 |
| 2010 | 1972.13 | 1492.28 | 1972.02 | 1969.57 | 514.07 | 1015.78 | 1018.44 | 1969.50 | 2504.99 | 1542.90 | 3457.08 | 3459.28 | 985.16 |
| 2020 | 2253.49 | 1787.40 | 2399.41 | 2322.23 | 611.34 | 1258.24 | 1262.07 | 2401.37 | 2428.61 | 1424.26 | 3781.16 | 4135.65 | 947.08 |
| 2030 | 2530.95 | 2101.60 | 2863.85 | 2670.22 | 734.11 | 1532.12 | 1536.54 | 2869.96 | 2545.94 | 1470.64 | 4057.28 | 4846.37 | 933.08 |
| 2040 | 2795.47 | 2206.09 | 2940.96 | 3000.37 | 789.70 | 1802.62 | 1574.14 | 3305.70 | 2698.99 | 1670.51 | 4355.16 | 5588.19 | 1007.83 |
If you are familiar with the python package pandas, you can access the pd.DataFrame directly.
df.data.head()
| model | scenario | region | variable | unit | year | value | |
|---|---|---|---|---|---|---|---|
| 0 | AIM-Enduse 12.1 | EMF27-450-Conv | ASIA | Emissions|CO2 | Mt CO2/yr | 2005 | 10540.74 |
| 1 | AIM-Enduse 12.1 | EMF27-450-Conv | ASIA | Emissions|CO2|Fossil Fuels and Industry | Mt CO2/yr | 2005 | 9126.18 |
| 2 | AIM-Enduse 12.1 | EMF27-450-Conv | ASIA | Primary Energy | EJ/yr | 2005 | 133.56 |
| 3 | AIM-Enduse 12.1 | EMF27-450-Conv | LAM | Emissions|CO2 | Mt CO2/yr | 2005 | 3285.00 |
| 4 | AIM-Enduse 12.1 | EMF27-450-Conv | LAM | Emissions|CO2|Fossil Fuels and Industry | Mt CO2/yr | 2005 | 1422.06 |
df.plot_lines({'variable': 'Emissions|CO2', 'region': 'World'})
df.validate('Primary Energy')
INFO:root:48 scenarios satisfy the criteria
df.validate({'Primary Energy': {'up': 515, 'year': 2010}})
INFO:root:9 data points do not satisfy the criteria (out of 48 scenarios)
| value | ||||||
|---|---|---|---|---|---|---|
| model | scenario | region | variable | unit | year | |
| AIM-Enduse 12.1 | EMF27-450-Conv | World | Primary Energy | EJ/yr | 2010 | 518.89 |
| EMF27-450-NoCCS | World | Primary Energy | EJ/yr | 2010 | 518.81 | |
| EMF27-550-LimBio | World | Primary Energy | EJ/yr | 2010 | 518.81 | |
| EMF27-Base-FullTech | World | Primary Energy | EJ/yr | 2010 | 518.81 | |
| EMF27-G8-EERE | World | Primary Energy | EJ/yr | 2010 | 518.64 | |
| REMIND 1.5 | EMF27-450-Conv | World | Primary Energy | EJ/yr | 2010 | 519.64 |
| EMF27-450-NoCCS | World | Primary Energy | EJ/yr | 2010 | 519.64 | |
| EMF27-550-LimBio | World | Primary Energy | EJ/yr | 2010 | 519.64 | |
| EMF27-Base-FullTech | World | Primary Energy | EJ/yr | 2010 | 519.64 |
df.validate(
{'Primary Energy|Coal': {'up': 400, 'year': 2050}},
filters={'region': 'World'},
exclude=False
)
INFO:root:2 data points do not satisfy the criteria (out of 48 scenarios)
| value | ||||||
|---|---|---|---|---|---|---|
| model | scenario | region | variable | unit | year | |
| GCAM 3.0 | AMPERE3-Base-EUback | World | Primary Energy|Coal | EJ/yr | 2050 | 424.09 |
| MERGE_EMF27 | EMF27-Base-FullTech | World | Primary Energy|Coal | EJ/yr | 2050 | 605.76 |
df.plot_lines({'variable': 'Temperature*'})
We now use the categorization feature of the pyam-analysis package.
By default, each model/scenario is assigned as "uncategorized".
The next function resets all scenarios back to "uncategorized". This may be helpful in this tutorial if you are going back and forth between cells.
df.reset_category()
df.category(
'Below 1.6C',
{'Temperature|Global Mean|MAGICC6|MED': {'up': 1.6, 'year': 2100}},
color='cornflowerblue',
display='list'
)
INFO:root:4 scenarios categorized as 'Below 1.6C'
| model | scenario |
|---|---|
| GCAM 3.0 | EMF27-450-Conv |
| EMF27-450-NoCCS | |
| REMIND 1.5 | EMF27-450-Conv |
| EMF27-450-NoCCS |
df.category(
'Below 2.0C',
{'Temperature|Global Mean|MAGICC6|MED': {'up': 2.0, 'year': 2100}},
filters={'category': 'uncategorized'},
color='forestgreen'
)
INFO:root:8 scenarios categorized as 'Below 2.0C'
df.category(
'Below 2.5C',
{'Temperature|Global Mean|MAGICC6|MED': {'up': 2.5, 'year': 2100}},
filters={'category': 'uncategorized'},
color='gold'
)
INFO:root:16 scenarios categorized as 'Below 2.5C'
df.category(
'Below 3.5C',
{'Temperature|Global Mean|MAGICC6|MED': {'up': 3.5, 'year': 2100}},
filters={'category': 'uncategorized'},
color='firebrick'
)
INFO:root:3 scenarios categorized as 'Below 3.5C'
df.category(
'Above 3.5C',
{'Temperature|Global Mean|MAGICC6|MED': {}},
filters={'category': 'uncategorized'},
color='magenta'
)
INFO:root:9 scenarios categorized as 'Above 3.5C'
df.category('uncategorized', display='list')
| category | model | scenario |
|---|---|---|
| uncategorized | AIM-Enduse 12.1 | EMF27-450-Conv |
| EMF27-450-NoCCS | ||
| EMF27-550-LimBio | ||
| EMF27-Base-FullTech | ||
| EMF27-G8-EERE | ||
| WITCH_EMF27 | EMF27-450-Conv | |
| EMF27-550-LimBio | ||
| EMF27-Base-FullTech |
Now, we again display the median global temperature increase for all scenarios, but we use the colouring by category to illustrate the common charateristics across scenarios.
df.plot_lines({'variable': 'Temperature*'}, color_by_cat=True)
As a last step, we display the aggregate CO2 emissions by category. This allows to highlight alternative pathways within the same category.
df.plot_lines(
{'variable': 'Emissions|CO2', 'region': 'World'},
color_by_cat=True
)