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.