Characterization of stressors¶
The characterization of stressors is a standard procedure to calculate the environmental and social impacts of economic activity. This is usually accomplished by multiplying (matrix-multiplication) the stressor-matrix with a characterization-matrix. Doing that in the matrix forms requires a 1:1 correspondence of the columns of the characterization matrix to the rows of the stressor-matrix.
Pymrio uses a different approach with matching the strings of the characterization table (given in long-format) to the available stressors. By doing that, the order of the entries in the characterization-table becomes unimportant. This implementation also allows to use characterization tables which includes characterization for stressors not present in the given satellite account. All characterizations relying on not available stressor will be automatically removed.
Example¶
For this example we use the test MRIO included in Pymrio. We also need the Pandas library for loading the characterization table and pathlib for some folder manipulation.
[1]:
from pathlib import Path
[2]:
import pandas as pd
[3]:
import pymrio
from pymrio.core.constants import PYMRIO_PATH # noqa
To load the test MRIO we use:
[4]:
io = pymrio.load_test()
and the characterization table with some foo factors can be loaded by
[5]:
charact_table = pd.read_csv(
(PYMRIO_PATH["test_mrio"] / Path("concordance") / "emissions_charact.tsv"),
sep="\t",
)
charact_table
[5]:
stressor | compartment | impact | factor | impact_unit | |
---|---|---|---|---|---|
0 | emission_type1 | air | air water impact | 0.002 | t |
1 | emission_type2 | water | air water impact | 0.001 | t |
2 | emission_type1 | air | total emissions | 1.000 | kg |
3 | emission_type2 | water | total emissions | 1.000 | kg |
4 | emission_type3 | land | total emissions | 1.000 | kg |
5 | emission_type1 | air | total air emissions | 0.001 | t |
This table contains the columns ‘stressor’ and ‘compartment’ which correspond to the index names of the test_mrio emission satellite accounts:
[6]:
io.emissions.F
[6]:
region | reg1 | reg2 | ... | reg5 | reg6 | |||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
sector | food | mining | manufactoring | electricity | construction | trade | transport | other | food | mining | ... | transport | other | food | mining | manufactoring | electricity | construction | trade | transport | other | |
stressor | compartment | |||||||||||||||||||||
emission_type1 | air | 1848064.80 | 986448.090 | 23613787.00 | 28139100.00 | 2584141.80 | 4132656.3 | 21766987.0 | 7842090.6 | 1697937.30 | 347378.150 | ... | 42299319 | 10773826.0 | 15777996.0 | 6420955.5 | 113172450.0 | 56022534.0 | 4861838.5 | 18195621 | 47046542.0 | 21632868 |
emission_type2 | water | 139250.47 | 22343.295 | 763569.18 | 273981.55 | 317396.51 | 1254477.8 | 1012999.1 | 2449178.0 | 204835.44 | 29463.944 | ... | 4199841 | 7191006.3 | 4826108.1 | 1865625.1 | 12700193.0 | 753213.7 | 2699288.3 | 13892313 | 8765784.3 | 16782553 |
2 rows × 48 columns
Theses index-names / columns-names need to match in order to match characterization factors to the stressors.
The other columns names can be passed to the characterization method. By default the method assumes the following column names:
- impact: name of the characterization/impact
- factor: the numerical (float) multiplication value for a specific stressor to derive the impact/characterized account
- impact_unit: the unit of the calculated characterization/impact
Alternative names can be passed through the parameters characterized_name_column, characterization_factors_column and characterized_unit_column.
Note, that units of stressor are currently not checked - units as given in the satellite account to be characterized are assumed. These can be seen by:
[7]:
io.emissions.unit
[7]:
unit | ||
---|---|---|
stressor | compartment | |
emission_type1 | air | kg |
emission_type2 | water | kg |
Also note, that the charact_table contains a characterization called ‘total emissions’, for which the calculation requires a stressor not present in the satellite account. This will be automatically omitted.
To calculate the characterization we use
[8]:
impacts = io.emissions.characterize(charact_table, name="impacts")
WARNING:root:Impact >total emissions< removed - calculation requires stressors not present in extension >Emissions<
The parameter name is optional, if omitted the name will be set to extension_name + _characterized
The method call above results in a pymrio.Extension which can be inspected with the usual methods, e.g.:
[9]:
impacts.F
[9]:
region | reg1 | reg2 | ... | reg5 | reg6 | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
sector | food | mining | manufactoring | electricity | construction | trade | transport | other | food | mining | ... | transport | other | food | mining | manufactoring | electricity | construction | trade | transport | other |
impact | |||||||||||||||||||||
air water impact | 3835.38007 | 1995.239475 | 47991.14318 | 56552.18155 | 5485.68011 | 9519.7904 | 44546.9731 | 18133.3592 | 3600.71004 | 724.220244 | ... | 88798.479 | 28738.6583 | 36382.1001 | 14707.5361 | 239045.093 | 112798.2817 | 12422.9653 | 50283.555 | 102858.8683 | 60048.289 |
total air emissions | 1848.06480 | 986.448090 | 23613.78700 | 28139.10000 | 2584.14180 | 4132.6563 | 21766.9870 | 7842.0906 | 1697.93730 | 347.378150 | ... | 42299.319 | 10773.8260 | 15777.9960 | 6420.9555 | 113172.450 | 56022.5340 | 4861.8385 | 18195.621 | 47046.5420 | 21632.868 |
2 rows × 48 columns
[10]:
impacts.F_Y
[10]:
region | reg1 | reg2 | ... | reg5 | reg6 | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
category | Final consumption expenditure by households | Final consumption expenditure by non-profit organisations serving households (NPISH) | Final consumption expenditure by government | Gross fixed capital formation | Changes in inventories | Changes in valuables | Export | Final consumption expenditure by households | Final consumption expenditure by non-profit organisations serving households (NPISH) | Final consumption expenditure by government | ... | Changes in inventories | Changes in valuables | Export | Final consumption expenditure by households | Final consumption expenditure by non-profit organisations serving households (NPISH) | Final consumption expenditure by government | Gross fixed capital formation | Changes in inventories | Changes in valuables | Export |
impact | |||||||||||||||||||||
air water impact | 183877.047 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 117347.860 | 0.0 | 0.0 | ... | 0.0 | 0.0 | 0.0 | 1305918.65 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
total air emissions | 62335.321 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 38566.929 | 0.0 | 0.0 | ... | 0.0 | 0.0 | 0.0 | 571278.30 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
2 rows × 42 columns
and the extension can be added to the MRIO
[11]:
io.impacts = impacts
and used for subsequent calculations:
[12]:
io.calc_all()
io.impacts.D_cba
[12]:
region | reg1 | reg2 | ... | reg5 | reg6 | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
sector | food | mining | manufactoring | electricity | construction | trade | transport | other | food | mining | ... | transport | other | food | mining | manufactoring | electricity | construction | trade | transport | other |
impact | |||||||||||||||||||||
air water impact | 4354.677050 | 384.125264 | 211698.404833 | 23912.313854 | 7032.640535 | 8548.387702 | 22000.497397 | 40123.553814 | 3800.328439 | 42.024811 | ... | 88433.836812 | 30080.437653 | 34765.284482 | 3227.857425 | 153582.938963 | 74236.159458 | 4580.343177 | 139321.814038 | 104944.664681 | 118394.939263 |
total air emissions | 2056.183383 | 179.423536 | 97493.003893 | 11887.591799 | 3342.905658 | 3885.883601 | 10750.267281 | 15821.524280 | 1793.337828 | 19.145605 | ... | 42095.049614 | 11386.614919 | 15172.354999 | 1345.317901 | 71450.748974 | 36831.672907 | 1836.695857 | 42415.684852 | 48054.090102 | 36022.975074 |
2 rows × 48 columns
Characterizing calculated results¶
The characterize method can also be used to characterize already calculated results. This works in the same way:
[13]:
io_aly = pymrio.load_test().calc_all()
[14]:
io_aly.emissions.D_cba
[14]:
region | reg1 | reg2 | ... | reg5 | reg6 | |||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
sector | food | mining | manufactoring | electricity | construction | trade | transport | other | food | mining | ... | transport | other | food | mining | manufactoring | electricity | construction | trade | transport | other | |
stressor | compartment | |||||||||||||||||||||
emission_type1 | air | 2.056183e+06 | 179423.535893 | 9.749300e+07 | 1.188759e+07 | 3.342906e+06 | 3.885884e+06 | 1.075027e+07 | 1.582152e+07 | 1.793338e+06 | 19145.604911 | ... | 4.209505e+07 | 1.138661e+07 | 1.517235e+07 | 1.345318e+06 | 7.145075e+07 | 3.683167e+07 | 1.836696e+06 | 4.241568e+07 | 4.805409e+07 | 3.602298e+07 |
emission_type2 | water | 2.423103e+05 | 25278.192086 | 1.671240e+07 | 1.371303e+05 | 3.468292e+05 | 7.766205e+05 | 4.999628e+05 | 8.480505e+06 | 2.136528e+05 | 3733.601474 | ... | 4.243738e+06 | 7.307208e+06 | 4.420574e+06 | 5.372216e+05 | 1.068144e+07 | 5.728136e+05 | 9.069515e+05 | 5.449044e+07 | 8.836484e+06 | 4.634899e+07 |
2 rows × 48 columns
[15]:
io_aly.impacts = io_aly.emissions.characterize(charact_table, name="impacts_new")
WARNING:root:Impact >total emissions< removed - calculation requires stressors not present in extension >Emissions<
Note, that all results which can be characterized directly (all flow accounts like D_cba, D_pba, …) are automatically included:
[16]:
io_aly.impacts.D_cba
[16]:
region | reg1 | reg2 | ... | reg5 | reg6 | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
sector | food | mining | manufactoring | electricity | construction | trade | transport | other | food | mining | ... | transport | other | food | mining | manufactoring | electricity | construction | trade | transport | other |
impact | |||||||||||||||||||||
air water impact | 4354.677050 | 384.125264 | 211698.404833 | 23912.313854 | 7032.640535 | 8548.387702 | 22000.497397 | 40123.553814 | 3800.328439 | 42.024811 | ... | 88433.836812 | 30080.437653 | 34765.284482 | 3227.857425 | 153582.938963 | 74236.159458 | 4580.343177 | 139321.814038 | 104944.664681 | 118394.939263 |
total air emissions | 2056.183383 | 179.423536 | 97493.003893 | 11887.591799 | 3342.905658 | 3885.883601 | 10750.267281 | 15821.524280 | 1793.337828 | 19.145605 | ... | 42095.049614 | 11386.614919 | 15172.354999 | 1345.317901 | 71450.748974 | 36831.672907 | 1836.695857 | 42415.684852 | 48054.090102 | 36022.975074 |
2 rows × 48 columns
Whereas coefficient accounts (M, S) are removed:
[17]:
io_aly.impacts.M
To calculated these use
[18]:
io_aly.calc_all()
io_aly.impacts.M
[18]:
region | reg1 | reg2 | ... | reg5 | reg6 | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
sector | food | mining | manufactoring | electricity | construction | trade | transport | other | food | mining | ... | transport | other | food | mining | manufactoring | electricity | construction | trade | transport | other |
impact | |||||||||||||||||||||
air water impact | 0.022428 | 0.052572 | 0.000259 | 0.225083 | 0.000295 | 0.000092 | 0.000952 | 0.000291 | 0.000092 | 0.016122 | ... | 0.007839 | 0.000481 | 0.000976 | 0.018407 | 0.000949 | 0.447245 | 0.007421 | 0.003222 | 0.001553 | 0.000739 |
total air emissions | 0.010865 | 0.025999 | 0.000127 | 0.111897 | 0.000140 | 0.000042 | 0.000465 | 0.000132 | 0.000044 | 0.007718 | ... | 0.003733 | 0.000182 | 0.000426 | 0.008250 | 0.000450 | 0.221901 | 0.002975 | 0.001207 | 0.000711 | 0.000277 |
2 rows × 48 columns
which will calculate the missing accounts.
For these calculations, the characterized accounts can also be used outside the MRIO system. Thus:
[19]:
independent_extension = io_aly.emissions.characterize(charact_table, name="impacts_new")
WARNING:root:Impact >total emissions< removed - calculation requires stressors not present in extension >Emissions<
[20]:
type(independent_extension)
[20]:
pymrio.core.mriosystem.Extension
[21]:
independent_extension.M
[22]:
independent_extension_calc = independent_extension.calc_system(x=io_aly.x, Y=io_aly.Y)
[23]:
independent_extension.M
[23]:
region | reg1 | reg2 | ... | reg5 | reg6 | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
sector | food | mining | manufactoring | electricity | construction | trade | transport | other | food | mining | ... | transport | other | food | mining | manufactoring | electricity | construction | trade | transport | other |
impact | |||||||||||||||||||||
air water impact | 0.022428 | 0.052572 | 0.000259 | 0.225083 | 0.000295 | 0.000092 | 0.000952 | 0.000291 | 0.000092 | 0.016122 | ... | 0.007839 | 0.000481 | 0.000976 | 0.018407 | 0.000949 | 0.447245 | 0.007421 | 0.003222 | 0.001553 | 0.000739 |
total air emissions | 0.010865 | 0.025999 | 0.000127 | 0.111897 | 0.000140 | 0.000042 | 0.000465 | 0.000132 | 0.000044 | 0.007718 | ... | 0.003733 | 0.000182 | 0.000426 | 0.008250 | 0.000450 | 0.221901 | 0.002975 | 0.001207 | 0.000711 | 0.000277 |
2 rows × 48 columns
Inspecting the used characterization table¶
Pymrio automatically adjust the characterization table by removing accounts which can not be calculated using a given extension. The removed accounts are reported through a warning message (e.g. “WARNING:root:Impact >total emissions< removed - calculation requires stressors not present in extension >Emissions<” in the examples above).
It is also possible, to obtain the cleaned characterization-table for inspection and further use. To do so:
[24]:
impacts = io.emissions.characterize(
charact_table, name="impacts", return_char_matrix=True
)
WARNING:root:Impact >total emissions< removed - calculation requires stressors not present in extension >Emissions<
This changes the return type from a pymrio.Extension to a named tuple
[25]:
type(impacts)
[25]:
pymrio.core.mriosystem.characterization
with
[26]:
impacts.extension
[26]:
<pymrio.core.mriosystem.Extension at 0x7f37e35c02e0>
and
[27]:
impacts.factors
[27]:
stressor | compartment | impact | factor | impact_unit | |
---|---|---|---|---|---|
0 | emission_type1 | air | air water impact | 0.002 | t |
1 | emission_type2 | water | air water impact | 0.001 | t |
5 | emission_type1 | air | total air emissions | 0.001 | t |
The latter is the characterization table used for the calculation.
For further information see the characterization docstring:
[28]:
print(io.emissions.characterize.__doc__)
Characterize stressors
Characterizes the extension with the characterization factors given in factors.
Factors can contain more characterization factors which depend on stressors not
present in the Extension - these will be automatically removed.
Note
----
Accordance of units is not checked - you must ensure that the
characterization factors correspond to the units of the extension to be
characterized.
Parameters
-----------
factors: pd.DataFrame
A dataframe in long format with numerical index and columns named
index.names of the extension to be characterized and
'characterized_name_column', 'characterization_factors_column',
'characterized_unit_column'
characterized_name_column: str (optional)
Name of the column with the names of the
characterized account (default: "impact")
characterization_factors_column: str (optional)
Name of the column with the factors for the
characterization (default: "factor")
characterized_unit_column: str (optional)
Name of the column with the units of the characterized accounts
characterization (default: "impact_unit")
name: string (optional)
The new name for the extension,
if None (default): name of the current extension with suffix
'_characterized'
return_char_matrix: boolean (optional)
If False (default), returns just the characterized extension.
If True, returns a namedtuple with extension and the actually used
characterization matrix.
_meta: MRIOMetaData, optional
Metadata handler for logging, optional. Internal
Returns
--------
pymrio.Extensions or
namedtuple with (extension: pymrio.Extension, factors: pd.DataFrame)
depending on return_char_matrix. Only the factors used for the calculation
are returned.