Exogenous model input from a file ================================= In this notebook we’ll demonstrate using an external data source to feed values into a model. We’ll use the carbon emissions dataset, and feed total emissions into a stock of excess atmospheric carbon: We’ll begin as usual by importing PySD and the machinery we need in order to deal with data manipulation and plotting. .. code:: ipython3 %pylab inline import pysd import pandas as pd .. parsed-literal:: Populating the interactive namespace from numpy and matplotlib We use `Pandas `__ library to import emissions data from a ``.csv`` file. In this command, we both rename the columns of the dataset, and set the index to the ‘Year’ column. .. code:: ipython3 emissions = pd.read_csv('../../data/Climate/global_emissions.csv', skiprows=2, index_col='Year', names=['Year', 'Total Emissions', 'Gas Emissions', 'Liquid Emissions', 'Solid Emissions', 'Cement Emissions', 'Flare Emissions', 'Per Capita Emissions']) emissions.head() .. raw:: html
Total Emissions Gas Emissions Liquid Emissions Solid Emissions Cement Emissions Flare Emissions Per Capita Emissions
Year
1751 3 0 0 3 0 0 NaN
1752 3 0 0 3 0 0 NaN
1753 3 0 0 3 0 0 NaN
1754 3 0 0 3 0 0 NaN
1755 3 0 0 3 0 0 NaN
.. code:: ipython3 model = pysd.read_vensim('../../models/Climate/Atmospheric_Bathtub.mdl') In our vensim model file, the value of the inflow to the carbon bathtub, the ``Emissions`` parameter, is set to zero. We want to instead have this track our exogenous data. .. code:: python Emissions= 0 Excess Atmospheric Carbon= INTEG ( Emissions - Natural Removal, 0) Natural Removal= Excess Atmospheric Carbon * Removal Constant Removal Constant= 0.01 Aligning the model time bounds with that of the dataset ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Before we can substitute in our exogenous data, however, we need to ensure that the model will execute over the proper timeseries. The initial and final times of the simulation are specified in the model file as: .. code:: ipython3 print('initial:', model.components.initial_time()) print('final:', model.components.final_time()) .. parsed-literal:: initial: 0 final: 100 However, the time frame of the dataset runs: .. code:: ipython3 print('initial:', emissions.index[0]) print('final:', emissions.index[-1]) .. parsed-literal:: initial: 1751 final: 2011 In order to run the model over a time series equal to that of the data set, we need to specify the appropriate initial conditions, and ask the run function to return to us timestamps equal to that of our dataset: .. code:: ipython3 res = model.run(initial_condition=(emissions.index[0], {'Excess Atmospheric Carbon': 0}), return_timestamps=emissions.index.values, return_columns=['Emissions', 'Excess Atmospheric Carbon']) res.head() .. raw:: html
Emissions Excess Atmospheric Carbon
1751 0 0.0
1752 0 0.0
1753 0 0.0
1754 0 0.0
1755 0 0.0
Pass in our timeseries data ~~~~~~~~~~~~~~~~~~~~~~~~~~~ In place of the constant value of ``emissions``, we want to substitute our dataset. We can do this in a very straightforward way by passing the Pandas ``Series`` corresponding to the dataset in a dictionary to the ``params`` argument of the run function. .. code:: ipython3 res = model.run(initial_condition=(emissions.index[0], {'Excess Atmospheric Carbon': 0}), return_timestamps=emissions.index.values, return_columns=['Emissions', 'Excess Atmospheric Carbon'], params={'Emissions': emissions['Total Emissions']}) .. code:: ipython3 res.plot(); .. image:: exogenous_timeseries_files/exogenous_timeseries_15_0.png