Analysis¶
This section describes post-hoc analyses that can be performed on solved models to extract insights about production, consumption, and the environmental and health impacts of food systems.
Statistics Extraction¶
The statistics extraction produces standardized CSV files summarizing key model outputs. These files provide a consistent interface for downstream analysis and visualization, extracting data from the solved PyPSA network using actual dispatch flows rather than capacity-based estimates.
Running the Extraction¶
# Extract all statistics for a scenario
tools/smk -j4 --configfile config/<name>.yaml -- \
results/{name}/analysis/scen-default/crop_production.csv
# Or request any downstream plot to trigger extraction automatically
Output Files¶
All statistics are written to results/{name}/analysis/scen-{scenario}/.
crop_production.csv — Crop production by crop, region, and country
Column |
Type |
Unit |
Description |
|---|---|---|---|
|
string |
— |
Crop identifier (e.g., |
|
string |
— |
Production region identifier |
|
string |
— |
ISO 3166-1 alpha-3 country code |
|
float |
Mt |
Production quantity in megatonnes |
Sources include single-crop production links, grassland production, and multicropping links (where multiple crops share the same land).
land_use.csv — Land allocation by crop, region, resource class, and water supply
Column |
Type |
Unit |
Description |
|---|---|---|---|
|
string |
— |
Crop identifier |
|
string |
— |
Production region identifier |
|
string |
— |
Land suitability class (e.g., |
|
string |
— |
Water regime ( |
|
string |
— |
ISO 3166-1 alpha-3 country code |
|
float |
Mha |
Cultivated area in million hectares |
For multicropping systems, land area is attributed to individual crops proportionally by their yield (efficiency) on that land.
animal_production.csv — Livestock product output by product and country
Column |
Type |
Unit |
Description |
|---|---|---|---|
|
string |
— |
Product identifier (e.g., |
|
string |
— |
ISO 3166-1 alpha-3 country code |
|
float |
Mt |
Production quantity in megatonnes |
food_consumption.csv — Food consumption and macronutrients by food and country
Column |
Type |
Unit |
Description |
|---|---|---|---|
|
string |
— |
Food identifier (e.g., |
|
string |
— |
ISO 3166-1 alpha-3 country code |
|
float |
Mt |
Total consumption in megatonnes |
|
float |
Mt |
Protein content in megatonnes |
|
float |
Mt |
Carbohydrate content in megatonnes |
|
float |
Mt |
Fat content in megatonnes |
|
float |
PJ |
Energy content in petajoules |
|
float |
g/person/day |
Per-capita daily consumption |
|
float |
g/person/day |
Per-capita daily protein intake |
|
float |
g/person/day |
Per-capita daily carbohydrate intake |
|
float |
g/person/day |
Per-capita daily fat intake |
|
float |
kcal/person/day |
Per-capita daily energy intake |
food_group_consumption.csv — Consumption aggregated by food group and country
Has the same columns as food_consumption.csv, except with food_group
instead of food. Food groups aggregate related foods (e.g., cereals,
fruits, red_meat) for higher-level analysis.
Example Usage¶
Load statistics in Python for custom analysis:
import pandas as pd
# Load crop production
production = pd.read_csv("results/opt/analysis/scen-default/crop_production.csv")
# Total wheat production globally
wheat_total = production[production["crop"] == "wheat"]["production_mt"].sum()
# Load consumption with per-capita values
consumption = pd.read_csv("results/opt/analysis/scen-default/food_consumption.csv")
# Average per-capita protein intake
avg_protein = consumption["protein_g_per_person_day"].mean()
GHG Intensity¶
The GHG intensity analysis computes greenhouse gas emissions attributable to each unit of food consumed. This provides a consumption-centric view of impacts, tracing emissions through trade and processing networks back to production.
GHG intensity measures the greenhouse gas emissions per unit of food consumed (kg CO₂e per kg food). Unlike production-based accounting, this consumption-attributed metric traces emissions through the entire supply chain: if wheat is grown in one country, milled into flour, and consumed in another, the emissions from farming, processing, and transport are all attributed to the final consumption.
GHG Attribution Methodology¶
The GHG attribution uses a flow-based approach via sparse matrix algebra. The network of production, processing, and trade links forms a directed graph where each node (bus) receives material from upstream and passes it downstream. Emissions occur at production links (e.g., fertilizer N₂O, enteric CH₄).
The key insight is that emission intensity propagates through the network: the intensity at any bus equals its direct emissions plus the weighted average of upstream intensities. This gives a linear system:
where \(\rho\) is the vector of emission intensities at each bus, \(e\) is the vector of direct emission contributions, and \(M\) is the weighted adjacency matrix (flow fractions). Solving \((I - M)\rho = e\) yields the consumption-attributed intensity at each food bus.
Running the GHG Extraction¶
# Extract consumption-attributed GHG intensity for a scenario
tools/smk -j4 --configfile config/<name>.yaml -- \
results/{name}/analysis/scen-default/ghg_attribution.csv
Output files:
results/{name}/analysis/scen-{scenario}/ghg_attribution.csvPer-country, per-food consumption-attributed GHG intensity including:
Column
Type
Unit
Description
countrystring
—
ISO 3166-1 alpha-3 country code
foodstring
—
Food identifier
food_groupstring
—
Food group
consumption_mtfloat
Mt
Consumption quantity
ghg_kgco2e_per_kgfloat
kgCO2e/kg
GHG intensity
ghg_usd_per_tfloat
USD/t
Monetized GHG damage
results/{name}/analysis/scen-{scenario}/ghg_attribution_totals.csvTotal consumption-attributed GHG emissions by country and food group:
Column
Type
Unit
Description
countrystring
—
ISO 3166-1 alpha-3 country code
food_groupstring
—
Food group
ghg_mtco2eqfloat
MtCO2eq
Total emissions attributed to consumption
Net Emissions¶
The net emissions extraction reads the solved network’s emission aggregation links directly, providing the absolute net GHG balance including negative emissions from spared land sequestration.
# Extract net emissions for a scenario
tools/smk -j4 --configfile config/<name>.yaml -- \
results/{name}/analysis/scen-default/net_emissions.csv
results/{name}/analysis/scen-{scenario}/net_emissions.csvNet GHG emissions per gas and total:
Column
Type
Unit
Description
gasstring
—
Gas type (co2, ch4, n2o, total)
net_mtco2eqfloat
MtCO2eq
Net emissions in CO2 equivalents
Health Impacts¶
The health impacts analysis computes marginal years of life lost (YLL) per unit of food consumed, based on dose-response curve derivatives at current population intake levels.
Health impact measures the years of life lost (YLL) per unit of food consumed. This is computed as the marginal effect—the derivative of the dose-response curve at current population intake levels. Foods with protective effects (fruits, vegetables, legumes) have negative values, while foods associated with health risks (processed meat, excess red meat) have positive values.
Health Attribution Methodology¶
Health impacts are computed by evaluating the slope of the piecewise-linear dose-response curves at current intake levels. For each (health cluster, risk factor) pair:
Current per-capita intake is computed from consumption flows and population
The slope of the log-relative-risk curve at this intake is determined
The chain rule converts this to YLL per unit intake change:
\[\frac{d(\text{YLL})}{d(\text{intake})} = \frac{\text{YLL}_\text{base}}{\text{RR}_\text{ref}} \cdot \text{RR} \cdot \frac{d(\log \text{RR})}{d(\text{intake})}\]Units are converted from YLL per g/capita/day to YLL per Mt food
The result captures how marginal changes in consumption affect population health outcomes, accounting for where each country currently sits on the dose-response curve.
Running the Health Extraction¶
# Extract health marginals for a scenario
tools/smk -j4 --configfile config/<name>.yaml -- \
results/{name}/analysis/scen-default/health_marginals.csv
Output files:
results/{name}/analysis/scen-{scenario}/health_marginals.csvPer-country, per-food-group marginal health impacts including:
Column
Type
Unit
Description
countrystring
—
ISO 3166-1 alpha-3 country code
food_groupstring
—
Food group (risk factor)
yll_per_mtfloat
YLL/Mt
Marginal years of life lost per megatonne
health_usd_per_tfloat
USD/t
Monetized marginal health damage
results/{name}/analysis/scen-{scenario}/health_totals.csvTotal years of life lost by health cluster:
Column
Type
Unit
Description
health_clusterint
—
Health cluster identifier
yll_myllfloat
MYLL
Total years of life lost in millions
Sample Results¶
The following figures show consumption-weighted global averages of GHG intensity and health impacts by food group:
Global average GHG intensity by food group (consumption-weighted). Animal products (red meat, dairy) show the highest emissions per kg, while plant-based foods generally have lower intensities.¶
Global average health impact by food group (consumption-weighted). Negative values indicate protective effects (fruits, vegetables, legumes, whole grains), while positive values indicate health risks. The magnitude reflects the marginal impact at current global intake levels.¶
Generating Global Average Plots¶
# Generate global average plots
tools/smk -j4 --configfile config/<name>.yaml -- \
results/{name}/plots/scen-default/marginal_ghg_global.pdf \
results/{name}/plots/scen-default/marginal_yll_global.pdf
Objective Breakdown¶
The objective breakdown analysis extracts the cost components that make up the model’s objective function, grouped into high-level categories. This enables analysis of how different cost drivers contribute to the total system cost.
Running the Objective Extraction¶
# Extract objective breakdown for a scenario
tools/smk -j4 --configfile config/<name>.yaml -- \
results/{name}/analysis/scen-default/objective_breakdown.csv
Output file:
results/{name}/analysis/scen-{scenario}/objective_breakdown.csvSingle-row CSV with cost categories in billion USD:
Column
Type
Unit
Description
crop_productionfloat
bn USD
Land use and yield-related costs
tradefloat
bn USD
Import/export costs
fertilizerfloat
bn USD
Synthetic fertilizer costs
processingfloat
bn USD
Food processing/conversion costs
consumptionfloat
bn USD
Consumption-related costs
animal_productionfloat
bn USD
Livestock production costs
feed_conversionfloat
bn USD
Feed processing costs
consumer_valuesfloat
bn USD
Utility from food consumption (negative)
biomass_exportsfloat
bn USD
Revenue from biomass exports (negative)
biomass_routingfloat
bn USD
Internal biomass flow costs
health_burdenfloat
bn USD
Health costs from YLL
ghg_costfloat
bn USD
Emissions costs
The script validates that extracted categories sum to the model’s reported objective value and raises an error if they don’t match (within 1% tolerance). It also raises errors for unrecognized component patterns to ensure the analysis is updated when the model structure changes.
See also
- Validation
A complementary analysis approach that fixes production and demand to observed values, using slack variables to reveal data inconsistencies.