Demo of a KDE plot beside timeseries set (Interactive) ====================================================== .. code:: ipython3 %pylab inline #%matplotlib inline #import matplotlib.pyplot as plt import mpld3 from mpld3 import plugins #mpld3.enable_notebook() #%matplotlib notebook # import pysd import numpy as np import pandas as pd import seaborn .. parsed-literal:: Populating the interactive namespace from numpy and matplotlib Load the model using PySD ~~~~~~~~~~~~~~~~~~~~~~~~~ The model is a basic, 1-stock carbon bathtub model .. code:: ipython3 model = pysd.read_vensim('../../models/Climate/Atmospheric_Bathtub.mdl') print(model.doc) .. parsed-literal:: Real Name Py Name Subscripts Units \ 0 Emissions emissions None None 1 Excess Atmospheric Carbon excess_atmospheric_carbon None None 2 FINAL TIME final_time None Month 3 INITIAL TIME initial_time None Month 4 Natural Removal natural_removal None None 5 Removal Constant removal_constant None None 6 SAVEPER saveper None Month 7 TIME STEP time_step None Month 8 Time time None None Limits Type Subtype Comment 0 (nan, nan) Constant Normal None 1 (nan, nan) Stateful Integ None 2 (nan, nan) Constant Normal The final time for the simulation. 3 (nan, nan) Constant Normal The initial time for the simulation. 4 (nan, nan) Auxiliary Normal None 5 (nan, nan) Constant Normal None 6 (0.0, nan) Auxiliary Normal The frequency with which output is stored. 7 (0.0, nan) Constant Normal The time step for the simulation. 8 (nan, nan) None None Current time of the model. Generate a set of parameters to use as input ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Here, drawing 100 constant values for the ``Emissions`` parameter from an exponential distribution .. code:: ipython3 n_runs = 100 runs = pd.DataFrame({'Emissions': np.random.exponential(scale=10000, size=n_runs)}) runs.head() .. raw:: html
Emissions
0 13139.288132
1 10414.796999
2 8505.605002
3 55251.743520
4 3650.497881
Run the model with the various parameters ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code:: ipython3 result = runs.apply(lambda p: model.run(params=dict(p))['Excess Atmospheric Carbon'], axis=1).T result.head() .. raw:: html
0 1 2 3 4 5 6 7 8 9 ... 90 91 92 93 94 95 96 97 98 99
0 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ... 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
1 13139.288132 10414.796999 8505.605002 55251.743520 3650.497881 7490.206883 5908.429778 4526.126740 3969.536964 42777.645014 ... 9654.733184 16864.050543 15725.059944 7426.330819 10563.284279 5586.831254 24433.431913 13290.730858 6245.476841 11057.440643
2 26147.183383 20725.446028 16926.153954 109950.969604 7264.490783 14905.511697 11757.775259 9006.992213 7899.378559 85127.513578 ... 19212.919037 33559.460581 31292.869289 14778.398329 21020.935715 11117.794196 48622.529506 26448.554408 12428.498913 22004.306879
3 39024.999681 30932.988567 25262.497417 164103.203428 10842.343756 22246.663463 17548.627285 13443.049031 11789.921738 127053.883456 ... 28675.523031 50087.916518 46705.000540 22056.945165 31374.010637 16593.447508 72569.736124 39474.799721 18549.690765 32841.704452
4 51774.037816 41038.455680 33515.477445 217713.914913 14384.418199 29514.403711 23281.570790 17834.745281 15641.559485 168560.989636 ... 38043.500985 66451.087897 61963.010478 29262.706532 41623.554810 22014.344287 96277.470675 52370.782582 24609.670698 43570.728050

5 rows × 100 columns

Draw a static plot showing the results, and a marginal density plot ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This would be for making graphics for a publication, where you don’t want an interactive view, but you want fine control over what the figure looks like. This is relatively simple, because we rely on the plotting library ``seaborn`` to generate the KDE plot, instead of working out the densities ourselves. .. code:: ipython3 import matplotlib.pylab as plt # define when to show the density density_time = 85 # left side: plot all traces, slightly transparent plt.subplot2grid((1,4), loc=(0,0), colspan=3) [plt.plot(result.index, result[i], 'b', alpha=.02) for i in result.columns] ymax = result.max().max() plt.ylim(0, ymax) # left side: add marker of density location plt.vlines(density_time, 0, ymax, 'k') plt.text(density_time, ymax, 'Density Calculation', ha='right', va='top', rotation=90) # right side: gaussian KDE on selected timestamp plt.subplot2grid((1,4), loc=(0,3)) seaborn.kdeplot(y=result.loc[density_time]) plt.ylim(0, ymax) plt.yticks([]) plt.xticks([]) plt.xlabel('Density') plt.suptitle('Emissions scenarios under uncertainty', fontsize=16); .. image:: marginal_density_plot_interactive_files/marginal_density_plot_interactive_9_0.png Interactive plot using python backend ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The following would be for lightweight exploration .. code:: ipython3 import matplotlib as mpl from ipywidgets import interact, IntSlider sim_time = 200 slider_time = IntSlider(description = 'Select Time for plotting Density', min=0, max=result.index[-1], value=1) .. code:: ipython3 @interact(density_time=slider_time) def update(density_time): ax1 = plt.subplot2grid((1,4), loc=(0,0), colspan=3) [ax1.plot(result.index, result[i], 'b', alpha=.02) for i in result.columns] ymax = result.max().max() ax1.set_ylim(0, ymax) # left side: add marker of density location ax1.vlines(density_time, 0, ymax, 'k') ax1.text(density_time, ymax, 'Density Calculation', ha='right', va='top', rotation=90) # right side: gaussian KDE on selected timestamp ax2 = plt.subplot2grid((1,4), loc=(0,3)) seaborn.kdeplot(y=result.loc[density_time], ax=ax2) ax2.set_ylim(0, ymax) ax2.set_yticks([]) ax2.set_xticks([]) ax2.set_xlabel('Density') plt.suptitle('Emissions scenarios under uncertainty', fontsize=16); .. parsed-literal:: interactive(children=(IntSlider(value=1, description='Select Time for plotting Density'), Output()), _dom_clas… Interactive figure with javascript background ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This script would prepare interactive graphics to share on a webpage, independent of the python backend. .. code:: ipython3 fig, ax = plt.subplots(3, 3, figsize=(6, 6)) fig.subplots_adjust(hspace=0.1, wspace=0.1) ax = ax[::-1] X = np.random.normal(size=(3, 100)) for i in range(3): for j in range(3): ax[i, j].xaxis.set_major_formatter(plt.NullFormatter()) ax[i, j].yaxis.set_major_formatter(plt.NullFormatter()) points = ax[i, j].scatter(X[j], X[i]) plugins.connect(fig, plugins.LinkedBrush(points)) .. image:: marginal_density_plot_interactive_files/marginal_density_plot_interactive_14_0.png