import pymrio

import pandas as pd
import numpy as np

"""
Explanation: Using pymrio without a parser (small IO example)
Pymrio provides parsing function to load existing MRIO databases. However, it is also possible to assign data directly to the attributes of an IOSystem instance.
This tutorial exemplify this functionality. The tables used here are taken from Miller and Blair (2009): Miller, Ronald E, and Peter D Blair. Input-Output Analysis: Foundations and Extensions. Cambridge (England); New York: Cambridge University Press, 2009. ISBN: 978-0-521-51713-3
Preperation
Import pymrio
First import the pymrio module and other packages needed:
End of explanation
"""


_sectors = ['sector1', 'sector2']
_regions = ['reg1']
_Z_multiindex = pd.MultiIndex.from_product(
                [_regions, _sectors], names = [u'region', u'sector'])

"""
Explanation: Get external IO table
For this example we use the IO table given in Miller and Blair (2009): Table 2.3 (on page 22 in the 2009 edition).
This table contains an interindustry trade flow matrix, final demand columns for household demand and exports and a value added row. The latter we consider as an extensions (factor inputs). To assign these values to the IOSystem attributes, the tables must be pandas
<a href="http://pandas.pydata.org/pandas-docs/dev/dsintro.html#dataframe">DataFrames</a> with <a href="http://pandas.pydata.org/pandas-docs/dev/indexing.html#hierarchical-indexing-multiindex">multiindex</a> for columns and index.
First we set up the Z matrix by defining the index of rows and columns. The example IO tables contains only domestic tables, but since pymrio was designed with multi regions IO tables in mind, also a region index is needed.
End of explanation
"""


Z = pd.DataFrame(
    data = np.array([
            [150,500],
            [200,100]]),
    index = _Z_multiindex,
    columns = _Z_multiindex
    )

Z

"""
Explanation: Next we setup the total Z matrix. Here we just put in the name the values manually. However, pandas provides several possibility to ease the <a href="http://pandas.pydata.org/pandas-docs/stable/io.html">data input</a>.
End of explanation
"""


_categories = ['final demand']
_fd_multiindex = pd.MultiIndex.from_product(
                 [_regions, _categories], names = [u'region', u'category'])

Y = pd.DataFrame(
    data=np.array([[350], [1700]]),
    index = _Z_multiindex,
    columns = _fd_multiindex)


Y

"""
Explanation: Final demand is treated in the same way:
End of explanation
"""


F = pd.DataFrame(
    data = np.array([[650, 1400]]),
    index = ['Payments_sectors'],
    columns = _Z_multiindex)


F

"""
Explanation: Factor inputs are given as 'Payment sectors' in the table:
End of explanation
"""


io = pymrio.IOSystem()

"""
Explanation: Include tables in the IOSystem object
In the next step, an empty instance of an IOSYstem has to be set up.
End of explanation
"""


io.Z = Z
io.Y = Y

"""
Explanation: Now we can add the tables to the IOSystem instance:
End of explanation
"""


factor_input = pymrio.Extension(name = 'Factor Input', F=F)

io.factor_input = factor_input

"""
Explanation: Extension are defined as objects within the IOSystem. The Extension instance can be instanced independently (the parameter 'name' is required):
End of explanation
"""


io.factor_input.unit = pd.DataFrame(data = ['USD'], index = F.index, columns = ['unit'])

"""
Explanation: For consistency and plotting we can add a DataFrame containg the units per row:
End of explanation
"""


str(io)

"""
Explanation: We can check whats in the system:
End of explanation
"""


io.calc_all()

"""
Explanation: At this point we have everything to calculate the full IO system.
Calculate the missing parts
End of explanation
"""


io.A

io.L

"""
Explanation: This gives, among others, the A and L matrix which we can compare with the tables given in Miller and Blair (2009) (Table 2.4 and L given on the next page afterwards):
End of explanation
"""


Ynew = Y.copy()
Ynew[('reg1','final_demand')] = np.array([[600],
                                          [1500]])

"""
Explanation: Update to system for a new final demand
The example in Miller and Blair (2009) goes on with using the L matrix to calculate the new industry output x for a changing finald demand Y. This step can easly reproduced with the pymrio module.
To do so we first have to set up the new final demand:
End of explanation
"""


io_new_fd = io.copy()

"""
Explanation: We copy the original IOSystem:
End of explanation
"""


io_new_fd.reset_all_to_coefficients()

"""
Explanation: To calculate for the new final demand we have to remove everything from the system except for the coefficients (A,L,S,M)
End of explanation
"""


io_new_fd.Y = Ynew

io_new_fd.calc_all()

"""
Explanation: Now we can assign the new final demand and recalculate the system:
End of explanation
"""


io_new_fd.x

"""
Explanation: The new x equalls the xnew values given in Miller and Blair (2009) at formula 2.13:
End of explanation
"""


io_new_fd.meta

"""
Explanation: As for all IO System, we can have a look at the modification history:
End of explanation
"""


