Illustrative example in a simplified economy

This page demonstrates Upright's approach to quantification of net impact using a simplified, illustrative example of the economy

Warning: advanced content

While simplified, the content is technical and expects an understanding of some mathematical concepts from the reader. Fully understanding the workings of the model at this level is not a prerequisite for using Upright data.

For convenience, some relevant fundamentals of hierarchical Bayesian inference are introduced in the appendix.

Introduction

This article demonstrates Upright's approach to quantification of net impact using a simplified, illustrative example of the economy: a self-sufficient island. While not exhaustive or reflective of all complexities of the full world economy and the complete net impact model, the example is intended to illustrate the major components of the model along with their principles and dynamics.

Finally, the article includes functional code snippets in Python that can be used to replicate the example data as well as explore how changes to the algorithm or input data would change the results. NumPy, Pandas and SciPy libraries are required to run some of the snippets.

import numpy as np
import pandas as pd

Main steps of quantifying net impact

The net impact model operates in two modules: the macromodel and the company model. The macromodel quantifies the net impact of products and services. Given this information, as well as product revenue shares and other company financial information, the net impact of companies can be determined.

This example is limited to quantification of net impact. In addition to net impact, the Upright net impact model additionally integrates information about UN SDGs, EU taxonomy, EU SFDR PAI indicators and CSRD DMA.

In this simplified example, quantifying the net impact of products and services in the macromodel is split into 6 interlinked components:

  1. Market size and value chain estimation of the global economy

  2. Summarization and generalization of information from scientific articles

  3. Summarization and generalization of information from complementary sources

  4. Conversion of summary information into impact intensities

  5. Allocation of impact across the value chain

  6. Scaling impacts between categories and determining the net impact

These steps correspond to the above visualization roughly as follows

Given net impact of products and services, the net impact of a company is based on the revenue-weighted average of the net impact of the products and services that the company markets.

This illustrative example omits or simplifies several aspects the Net Impact Model to make the main concepts and dynamics of the model easier to understand. Such omissions and simplifications include but are not limited to

  • A very simplified product graph, both in number of products and their value chain links

  • Omission of product-like entities, including non-marketable phenomena like yoga

  • A simplified set of impact categories

  • A simplified set of data sources for each included impact category

  • Simplifications to all major computations made in quantifying net impact

  • Simplifications in how company scores are aggregated from product level scores

Definitions

Before discussing how net impact is quantified, it is useful to define some key concepts and terms that will be used throughout the example.

Product taxonomy

The Product taxonomy refers to the products and services present in the economy, along with grouping, expressed with "is a" relationships.

Our simple island economy consists of 5 products: Farming Tools (TOOLS), Fertilizer (FERTI), Growing apples (APPLE), Growing pears (PEARA) and Apple Juice (APLJU).

Together APPLE and PEARA are considered Fruits (FRUIT).

FERTI, SEEDS, APPLE, PEARA and APLJU are considered to be leaf products, since they are not considered to be groups of more specific products. FRUIT conversely is a non-leaf product.

It is worth noting that leaf products represent a mutually exclusive and collectively exhaustive set of products and services. Therefore several algorithms of the net impact model operate on leaf products to ensure that impact is counted exactly once. In summary, steps 2 and 3 operate on all products, and yield "flattened" information only for leaf products. Steps 4 and 5 operate on leaf products. After step 5, non-leaf scores are computed as market size weighted average of respective leaf scores. Processing from step 6 onwards operate again on all products.

The actual net impact model contains orders of magnitude more products and product-like entities in a deeply nested hierarchy.

Furthermore, the actual Product taxonomy includes additional product-like entities like Phenomena, that products enable indirectly. Examples include yoga: while yoga is not a marketable product or service, the phenomenon has been researched substantially and is enabled by commercial products and services like yoga mats or yoga instruction.

Finally the product taxonomy includes so called mixin products that describe more specific variants of products that e.g., use a specific raw material or are supplied to a specific customer segment.

Code Snippet
products = {
    "TOOLS",
    "FERTI",
    "FRUIT",
    "APPLE",
    "PEARA",
    "APLJU"
}

parentage = {
    "APPLE": "FRUIT",
    "PEARA": "FRUIT"
}

leaves = [p for p in products if p not in parentage.values()]

Impact model

In this illustrative example, only two positive and two negative impact categories are considered: Job creation (JOBS, positive), Use of Scarce Human Capital (SHC, negative), Health (HEALTH, positive) and Environmental harm (ENVIRONMENT, negative).

The actual Net Impact Model considers 19 distinct impact categories across Society, Knowledge, Health, Environment. Many impact categories like Physical Health consider both positive and negative impacts.

Code Snippet
impacts = {
    ("JOBS", "P"),
    ("SHC", "N"),
    ("HEALTH", "P"),
    ("ENVIRONMENT", "N")
}

Units

The net impact profiles of entities are expressed in relative or absolute scores. See the whitepaper on estimating the net impact of companies for details on their definitions.

For convenience reasons, two additional units are used internally when quantifying net impact:

  1. Impact Share: the share of impact attributed to an entity, relative to impact attributed to the global economy.

  2. Impact Intensity: The Impact Share of an entity divided by the market share of the entity

The Impact Share of the whole global economy is 1.0. The Impact Intensity of the global economy 1.0, so that products with below 1.0 Impact Intensity have below average rate of generating impact, and vice versa for products with above 1.0 Impact Intensity.

Conventions

For convenience, products and services are plainly referred to as products.

Market size and value chain estimation of the global economy

A global market model underpins most aspects of the net impact modeling of products and services. The market model provides estimates for product market sizes as well as value flows between products. These estimates are used to assess relative sizes of products as well as to attribute impact along value chains (see Allocation of impact across the value chain).

Market size estimation

The market size estimation model attempts to estimate the global market sizes of all products, based on available, reliable but partial information.

Reliable market sizes are often available for industries, other broad subdivisions or partially for specific economic activities. Therefore market sizes need to be imputed for products and services where direct information is not available. Proxies used as allocation keys include volume of research (see below) among others.

Imputation of missing market sizes yields market sizes for both leaf and non-leaf products such, that the market size of a non-leaf product is the sum total of its constituent leaf products.

Code Snippet
market_sizes = {
    "TOOLS": 23,
    "FERTI": 30,
    "FRUIT": 100, # sum of APPLE and PEARA
    "APPLE": 60,
    "PEARA": 40,
    "APLJU": 20
}
total_global_market = sum(market_sizes[leaf] for leaf in leaves)
market_shares = {
    product: market_size / total_global_market
    for product, market_size in market_sizes.items()
}

Value flow model

The value flow model attempts to find a set of flows between products such that they meet two desired properties for all leaf products in the graph:

  1. The total inflow into a given product should equal the market size of the product minus the value add of the product

  2. The total outflow from a product should equal the business market size of the product

The value add of a product can be generalized from e.g., industry level aggregates similarly as for the product market size model.

The business market size of a product is the part of the revenue of the product that is sold to businesses (as opposed to consumers).

In practice, sources of industry and subdivision market size estimates are rarely fully consistent. As a consequence no single solution would satisfy the two above properties for all leaf products in the graph. Therefore the value flow model aims to find a consensus between all input data using constrained optimization. The optimization problem is formulated with soft constraints, where deviation from the above properties is penalized in proportion of the deviation. The optimizer tries to find this solution by minimizing the average deviation of the properties across all leaf products.

In our example the value chains are straightforward:

  • TOOLS and FERTI are needed to produce APPLE and PEARA

  • APLJU is made of APPLE

It is worth noting that TOOLS and FERTI can be understood as purely B2B products that are fully used to produce other products, whereas APPLE, PEARA and APLJU are directly consumed such that their total outflow to other products is less than their respective market sizes.

Code Snippet
value_adds = {
    "TOOLS": 5,
    "FERTI": 10,
    "FRUIT": 45, # sum of APPLE and PEARA
    "APPLE": 25,
    "PEARA": 20,
    "APLJU": 5
}

flows = {
    ("TOOLS", "APPLE"): 15,
    ("TOOLS", "PEARA"): 8,
    ("FERTI", "APPLE"): 20,
    ("FERTI", "PEARA"): 12,
    ("APPLE", "APLJU"): 15,
}

Summarization and generalization of information from scientific articles

Scientific articles are used in quantifying impact in most impact categories because the same methodology can be applied broadly to different definitions of impact.

The idea of this step is to associate research to all products in the net impact model. In subsequent algorithms, the model expects impact to be mutually exclusive and collectively exhaustive. Therefore information is generalized by propagating relevant information about non-leaf products to their leaf products.

In this example, scientific information is only used to quantify HEALTH and ENVIRONMENT impacts, i.e., impacts where complementary data sources are not considered. In the actual net impact model, several impact categories rely on both scientific and complementary data sources.

Code Snippet
unnormalized_scores = {}

Causality classification

The causality classification algorithm is introduced in Extraction of causal links from scientific literature. In this example, the relevant article counts are denoted as:

  1. NpN_p: the total number of articles discussing the product pp

  2. Rp,iR_{p,i}: the total number of articles that find that product pp causes impact ii

Code Snippet
total_article_counts = { # N_p in the above
    "TOOLS": 250,
    "FERTI": 100,
    "FRUIT": 200,
    "APPLE": 100,
    "PEARA": 10,
    "APLJU": 50,
}

relevant_article_counts = { # R_{p,i} in the above
    ("FERTI", "JOBS", "P"): 1,
    ("FERTI", "ENVIRONMENT", "N"): 15,
    ("FRUIT", "HEALTH", "P"): 12,
    ("FRUIT", "ENVIRONMENT", "N"): 5,
    ("APPLE", "HEALTH", "P"): 4,
    ("APPLE", "ENVIRONMENT", "N"): 4,
    ("PEARA", "HEALTH", "P"): 5,
    ("PEARA", "ENVIRONMENT", "N"): 1,
    ("APLJU", "HEALTH", "P"): 1,
}

In order to use these article counts for quantifying Net Impact, they need to be translated into impact intensities. This translation relies on two main assumptions.

A1: The ratio of relevant to total articles correlates with impact intensity

  • A product with 10/100 relevant articles probably has a higher impact than a product with 1/100 relevant articles.

A2: The amount of total articles correlates with the certainty of the estimate

  • 100/1000 is a more reliable indication of impact than 1/10 even though they have the same ratio.

  • The same applies for low-intensity estimates; 0/1000 is a stronger indication of low impact than 0/10.

Information is also generalized at this stage to identify e.g., how information about FRUIT in general applies to APPLE and PEARA specifically.

In practice this is achieved with a hierarchical Bayesian inference model. The appendix "Primer in hierarchical Bayesian inference and Poisson-Gamma models" provides a brief introduction to hierarchical Poisson-Gamma models.

The approach to summarize scientific information applies the Poisson-Gamma model by treating the total article counts as exposure, or the amount of observations about a particular product's impact, and the relevant article counts as Poisson distributed counts in the given exposure. Parent products are treated as priors of their child products such that leaf products also consider the article counts of all their parents.

Additionally products relative sizes are factored in when counting parent articles in order to put general research in the same scale as the more specific research.

Denoting the market size of a product with mpm_p and the parent of p as p^\hat{p} the combined inference of the impact of pp is then

  • In the actual net impact model, the product hierarchy is deeply nested. Therefore inheritance is factored in across layers rather than in just one level

  • Actual scientific research exhibits a significant snowball effect, where research into a topic attract more research into the same topic. This violates the assumption of independent events in the Poisson process and would lead to a heavily polarized inference. The article counts are therefore compressed to better align to the distribution of impact intensities from other sources measuring the same impact.

Code Snippet
def get_flattened_bibliometric_score(leaf, impact, valence):
  my_total_article_count = total_article_counts.get(leaf, 0)
  my_relevant_article_count = relevant_article_counts.get(
      (leaf, impact, valence), 0
  )
  
  parent = parentage.get(leaf, None)
  parent_total_article_count = total_article_counts.get(parent, 0)
  parent_relevant_article_count = relevant_article_counts.get(
      (parent, impact, valence), 0
  )

  if parent:
    siblings = [s for s in leaves if parentage.get(s, None) == parent]
    sibling_size = sum(market_sizes.get(s, 0) for s in siblings)
    my_relative_size = market_sizes.get(leaf, 0) / sibling_size
  else:
    my_relative_size = 1
  
  return (
      (my_relevant_article_count + my_relative_size * parent_relevant_article_count) / 
      (my_total_article_count + my_relative_size * parent_total_article_count)
  )

unnormalized_scores[("HEALTH", "P")] = {
    leaf: get_flattened_bibliometric_score(leaf, 'HEALTH', 'P')
    for leaf in leaves
}
unnormalized_scores[("ENVIRONMENT", "N")] = {
    leaf: get_flattened_bibliometric_score(leaf, 'ENVIRONMENT', 'N')
    for leaf in leaves
}

Summarization and generalization of information from complementary sources

The body of scientific research is a great source of insight into impacts like Physical Health or Meaning & Joy, but some impact categories have other sources of reliable information that are informative about impact intensities before value chain allocation. Scarce Human Capital and Jobs are great examples: OECD collects aggregate data about the aggregate revenue, employed headcount and education rates of economic activities. The Upright Net Impact model takes such information into account in a similar fashion as scientific research.

The simplest way to take this information into account is to compute a proxy of intensity for the subdivisions available, and then propagate the intensity to the respective leaf products.

Code Snippet
def get_flattened_supplemental_score(leaf, intensities):
  if leaf in intensities:
    return intensities[leaf]
  parent = parentage[leaf]
  return intensities[parent]

In this example, Scarce Human Capital is proxied by the relative rate at which a product requires employees with tertiary education.

Code Snippet
tertiary_education_ratios = {
    "TOOLS": 0.7,
    "FERTI": 0.4,
    "FRUIT": 0.2,
    "APLJU": 0.3
}
average_education_ratio = sum(
    value * market_shares[product]
    for product, value in tertiary_education_ratios.items()
)

score_shc = {
    product: education_ratio / average_education_ratio
    for product, education_ratio in tertiary_education_ratios.items()
}
unnormalized_scores[("SHC", "N")] = {
    leaf: get_flattened_supplemental_score(leaf, score_shc)
    for leaf in leaves
}

Job creation is proxied similarly by looking at relative rate at which the product creates jobs relative to revenue.

Code Snippet
turnovers_by_fte = {
    "TOOLS": 50,
    "FERTI": 40,
    "FRUIT": 20,
    "APLJU": 30
}
average_turnover_by_fte = sum(
    value * market_shares[product]
    for product, value in turnovers_by_fte.items()
)

score_jobs = {
    product: average_turnover_by_fte / turnover_by_fte # Note inverse
    for product, turnover_by_fte in turnovers_by_fte.items()
}
unnormalized_scores[("JOBS", "P")] = {
    leaf: get_flattened_supplemental_score(leaf, score_jobs)
    for leaf in leaves
}

Conversion of summary information into impact intensities

The above information from scientific articles and other reliable sources is almost ready for use in quantifying net impact. The final transformation that is needed to make these quantities comparable is normalization. By definition, the market weighted average of impact intensities across leaf products is 1.

Denoting the unnormalized impact value of product pp with vpv_p and the the market size of pp with mpm_p , the scaling factor applied to unnormalized scores is

pmpvppmp.\frac{\sum_p m_p v_p}{\sum_p m_p}.

This yields the following impact intensities for our net impact model

ProductENVIRONMENT, NSHC, NJOBS, PHEALTH, P

PEARA

0.74

0.64

1.26

2.41

APPLE

0.71

0.64

1.26

1.13

FERTI

3.35

1.28

0.63

0

TOOLS

0

2.24

0.5

0

APLJU

0

0.96

0.84

0.44

Code Snippet
def normalize_scores(scores, market_shares):
  average = sum(
      scores.get(leaf, 0) * market_shares.get(leaf, 0) for leaf in leaves
  )
  return {
      leaf: scores.get(leaf, 0) / average
      for leaf in leaves
  }


leaf_intensities = {
    impact: normalize_scores(unnormalized_scores[impact], market_shares)
    for impact in impacts
}

Allocation of impact across the value chain

The principles behind value chain allocation are outlined in Allocation of impact across value chains.

Participating value-add in the example case

Recall the market sizes, value-adds and value flows from step 1. One way to quantify participating value-add is by traversing the value chain up and down from each product and computing the participation of product aa in product bb as

pa,b=vaRR(a,b)(s,t)Rfs,tF(s,t),p_{a,b} = v_a \sum_{R \in \mathcal{R}(a,b)} \prod_{(s,t) \in R} \frac{f_{s,t}}{F(s,t)},

where

  • vpv_p represents the value-add of product pp

  • R(a,b)\mathcal{R}(a,b) represents the set of routes between products aaand bb, where each route is defined as a set of adjacent edges leading from aa to bb

  • fs,tf_{s,t} represents the flow from product ss to product tt

  • F(s,t)F(s, t) yields the comparable flow for product ss with respect to product t. The comparable flow depends on whether ss is downstream or upstream of tt. In the case of the former, F(s,t)F(s, t) is the market size of ss. Otherwise, it’s the total inflow into ss i.e., the market size of ss minus the value-add of ss

Following this logic, the participation of TOOLS in APPLE would be

pTOOLS,APPLE=vTOOLSfTOOLS,APPLEF(TOOLS,APPLE)=515233.26.p_{TOOLS, APPLE} = v_{TOOLS} \frac{f_{TOOLS,APPLE}}{F(TOOLS, APPLE)} = 5 * \frac{15}{23} \approx 3.26.

Similarly the participation of APLJU in FERTI would be

pAPLJU,FERTI=vAPLJUfAPLJU,APPLEF(APLJU,APPLE)fAPPLE,FERTIF(APPLE,FERTI)=5152052060252.86.p_{APLJU, FERTI} = v_{APLJU} \frac{f_{APLJU,APPLE}}{F(APLJU, APPLE)}\frac{f_{APPLE,FERTI}}{F(APPLE, FERTI)} = 5 * \frac{15}{20-5} * \frac{20}{60-25} \approx 2.86.

Applying the same logic yields participations across the whole modelled economy. It is worth noting that a product does not necessarily participate in the impact of all other products.

Participations (from-to)PEARAAPPLEFERTITOOLSAPLJU

PEARA

20

0

12

8

0

APPLE

0

25

14.29

10.71

6.25

FERTI

4

6.67

10

0

1.67

TOOLS

1.74

3.26

0

5

0.82

APLJU

0

5

2.86

2.14

5

Code Snippet
from collections import defaultdict

def determine_participations(product):
  relative_participations = [
      {
          "target": product,
          "relative_flow": 1
      },
      *determine_relative_participations(product, 'd'),
      *determine_relative_participations(product, 'u')
  ]
  value_add = value_adds[product]
  participations = defaultdict(int)
  for relative_participations in relative_participations:
    target = relative_participations["target"]
    relative_flow = relative_participations["relative_flow"]
    participations[target] += value_add * relative_flow
  return participations


def determine_relative_participations(product, direction):
  relative_flows = get_relative_flows(product, direction)
  target_ix = 1 if direction == 'd' else 0
  my_relative_participations = [
      {
        "target": od[target_ix],
        "relative_flow": relative_flow
      }
      for od, relative_flow in relative_flows.items()
  ]

  nested_relative_participations = [
      {
        "target": y["target"],
        "relative_flow": x["relative_flow"] * y["relative_flow"]    
      }
      for x in my_relative_participations
      for y
      in determine_relative_participations(x["target"], direction)
  ]
  return [*my_relative_participations, *nested_relative_participations]


def get_relative_flows(product, direction):
  flows = get_flows(product, direction)
  source_ix = 0 if direction == 'd' else 1
  return {
      od: flow / get_comparable_flow(od[source_ix], direction)
      for od, flow in flows.items()
  }

def get_flows(product, direction):
  ix = 0 if direction == 'd' else 1
  return {
      od: flow
      for od, flow in flows.items()
      if od[ix] == product
  }

def get_comparable_flow(product, direction):
  if direction == 'u':
    return market_sizes[product] - value_adds[product]
  return market_sizes[product]
  
participations = {
    (leaf, target): participation
    for leaf in leaves
    for target, participation in determine_participations(leaf).items()
}
df_participations = (
  pd.Series(participations)
  .unstack(1, fill_value=0)
  .loc[leaves, leaves]
)

Full scores

A table of all participations between all products of the imaginary island can be used to determine how much impact each product should inherit from each other product. One approach to translate participations into allocations is to look at the relative share of each participation in a given product.

For example, the sum total of all participations in APPLE is approximately 39.93, of which TOOLS represents 3.2639.930.08\frac{3.26}{39.93} \approx 0.08.

Applying the same logic to all leaf products yields the full matrix of inheritance factors

Inheritance (from-to)PEARAAPPLEFERTITOOLSAPLJU

PEARA

0.78

0

0.16

0.07

0

APPLE

0

0.63

0.17

0.08

0.13

FERTI

0.31

0.36

0.26

0

0.07

TOOLS

0.31

0.41

0

0.19

0.08

APLJU

0

0.46

0.12

0.06

0.36

Code Snippet
inheritance_factors = (
    df_participations
    .div(df_participations.sum(axis=0), axis=1)
    .T
    .loc[leaves, leaves]
)

These inheritance ratios are in absolute scale, which should be taken into account when using them to inherit impact from one product to another:

where

  • sF,p,is_{F,p,i} represents the impact intensity of product pp and impact ii, including value-chain allocation

  • sf,p,is_{f,p,i} represents the impact intensity of product pp and impact ii, not including value-chain allocation

  • mpm_p is the market size of product pp

  • PP represents the set of all leaf products

Applying the same logic across products yields inherited impact intensities for each product and impact

ProductENVIRONMENT, NSHC, NJOBS, PHEALTH, P

APPLE

1.06

1.13

1.11

0.77

APLJU

0.63

0.94

0.89

0.58

TOOLS

0.24

0.69

0.56

0.55

FERTI

1.25

0.75

0.91

0.91

PEARA

1.35

1.19

1.21

1.87

Code Snippet
market_sizes_v = pd.Series(market_sizes)

def compute_full_intensities(organic_intensities):
  intensities_v = pd.Series(organic_intensities).reindex(leaves, fill_value=0)
  return (
      inheritance_factors.T
      .dot(intensities_v * market_sizes_v[leaves])
      .div(market_sizes_v[leaves])
      .loc[leaves]
  )
  
df_leaf_intensities = pd.DataFrame(leaf_intensities)
full_intensities = pd.DataFrame({
    impact: compute_full_intensities(leaf_intensities[impact])
    for impact in impacts
})

Non-leaf scores (Fruit)

Having allocated impact across leaf products, the scores of non-leaf products are determined in a simple upward pass of the product taxonomy, where the score of a non-leaf product is the market weighted average of its leaf products.

The net impact scores of FRUIT is therefore a weighted average of the scores of APPLE and PEARA.

ProductENVIRONMENT, NSHC, NJOBS, PHEALTH, P

APPLE

1.06

1.13

1.11

0.77

APLJU

0.63

0.94

0.89

0.58

TOOLS

0.24

0.69

0.56

0.55

FERTI

1.25

0.75

0.91

0.91

PEARA

1.35

1.19

1.21

1.87

FRUIT

1.17

1.16

1.15

1.21

Size factors

Size factors of impact categories represent relative sizes of the impact categories. There are two size factors for each impact category, one representing costs and one representing benefits. They are derived from estimates of aggregate costs and benefits that all products and services create within each impact category. Upright bases the estimates of costs and benefits on classical measures of economic cost used by The World Bank, WHO and IMF, and others.

In this illustrative example, the size factors are as follows:

ImpactSize factor

JOBS

1.2

SCH

0.8

HEALTH

1.2

ENVIRONMENT

1.6

Applying the size factors to the impact intensities yields the scores for each product and impact. These scores now correspond to relative scores, i.e., scores in which results of the net impact model are presented in. Most notably these relative scores are comparable across impact categories. For example, while the impact intensities of ENVIRONMENT and HEALTH for the product FRUIT are roughly equal, the high relative weight of ENVIRONMENT implies that the environmental harm of FRUIT outweighs its health benefits.

ProductENVIRONMENT, NHEALTH, PJOBS, PSHC, N

APPLE

1.69

0.93

1.33

0.91

APLJU

1.01

0.7

1.07

0.75

TOOLS

0.38

0.66

0.67

0.56

FERTI

2

1.09

1.09

0.6

PEARA

2.16

2.25

1.45

0.95

FRUIT

1.88

1.46

1.38

0.93

Code Snippet
size_factors = pd.Series({
    ("JOBS", "P"): 1.2,
    ("SHC", "N"): 0.8,
    ("HEALTH", "P"): 1.2,
    ("ENVIRONMENT", "N"): 1.6
})
product_rel_scores = full_intensities_all * size_factors

Net Impact Ratio

The Net Impact Ratio (NIR) represents the aggregate impact of a product across impact categories. It is defined as (PN)/P(P-N)/P where PP and NNare the total positive and negative impacts of the product respectively.

In our illustrative example, TOOLS have the highest NIR because they contribute indirectly to the health benefits of APPLE and PEARA, but they do not participate in the environmental harm of FERTI.

Conversely, FERTI comes last due to its direct environmental harm that is not offset by indirect health benefits from APPLE and PEARA.

Finally APPLE, PEARA and APLJU directly contribute to health benefits, but unlike TOOLS, they also participate in the environmental harm of FERTI.

ProductNIR

APPLE

-0.15

APLJU

0

TOOLS

0.29

FERTI

-0.19

PEARA

0.16

FRUIT

0.01

Code Snippet
positive = [(c, v) for c, v in impacts if v == 'P']
negative = [(c, v) for c, v in impacts if v == 'N']

def compute_nir(rel_scores):
  sum_p = rel_scores.loc[:, positive].sum(axis=1)
  sum_n = rel_scores.loc[:, negative].sum(axis=1)
  return ((sum_p - sum_n) / sum_p).rename('NIR')

Company impact scores

Similar to non-leaf products, the aggregate impact scores of companies is the revenue weighted average of the products and services the company markets. This illustrative example has two companies:

Equipment Co.

ProductReveneue Share

FERTI

40%

TOOLS

60%

Fruit Co.

ProductReveneue Share

FRUIT

80%

APLJU

20%

It is worth noting that Fruit Co only discloses that they retail FRUIT without specifying exactly what fruit this includes. Therefore the revenue mix has the aggregate product FRUIT, and the quantification assumes that in the absence of more specific information, Fruit Co. markets APPLE and PEARA in proportion to their market sizes.

  • In the actual Net Impact Model, company specific data is used to adjust some scores of some impact categories where the data is relevant. For example, a company employing more workforce than expected by the product based score will see an increase in its direct job creation score.

  • The actual Net Impact Model allows expressing detailed information about the value chains and other operational details of how a company produces a product or service. For example, the use of recycled raw materials, sales to specific customer segments or energy efficient manufacturing processes can be accounted in this way.

The Net Impact of Equipment Co. is higher than that of Fruit Co. due to the majority of their revenue coming from TOOLS rather than FERTI. The opposite would be true if the revenue shares were reversed.

CompanyNIR

EQUIPMENT_CO

0.04

FRUIT_CO

0.01

Code Snippet
companies = {
    "EQUIPMENT_CO": {
        "FERTI": 0.4,
        "TOOLS": 0.6
    },
    "FRUIT_CO": {
        "FRUIT": 0.8,
        "APLJU": 0.2
    }
}

def compute_company_scores(product_set):
  ps_v = pd.Series(product_set)
  p_ix = ps_v.index
  return product_rel_scores.loc[p_ix, :].T.dot(ps_v)

company_rel_scores = pd.DataFrame({
    company: compute_company_scores(product_set)
    for company, product_set in companies.items()
}).T

company_nirs = compute_nir(company_rel_scores)

Last updated