Choosing a value: the axes
Numbers checked against the live data on
The default row, is_default_indicator AND is_latest_activity_year, gives one sensible number per factor. When you need another one, such as a different GWP characterization, the producer-price variant of a spend factor, a market-based grid mix or an earlier year, drop the flag that hides it and filter the axis you want instead. The values of one factor are always alternatives: select one per axis, never add them.
What the default collapses#
The two flags work on independent axes. You can relax one and keep the other.
| flag | axis it collapses | true on |
|---|---|---|
is_default_indicator |
Methodology: GWP set, horizon, characterization model, price basis, grid mix | One value per factor, release and reference year: the value the import elects as the sensible default |
is_latest_activity_year |
Time: the accounting years a value applies to | The rows for the newest accounting year the factor covers |
A third filter is already applied for you: factors_flat serves each library's current release only. A publisher that ships two co-valid document lines at once (a stream), or two system models, has one current release per line and the view serves each of them. None of the public libraries does that today, so each has exactly one release here and system_model and stream are NULL throughout.
Pin a factor value to a release shows how to hold on to a number when the next one lands.
Dropping is_default_indicator returns every methodology sibling. Dropping is_latest_activity_year returns one row per accounting year the factor covers, which is what Get the value for a past year filters.
The axes#
The populated on column names the public libraries these docs write their examples against. Other libraries in factor search fill the same columns, so read it as "where to see this axis at work", not as the full list of publishers that carry it.
| axis | column | kind | populated on |
|---|---|---|---|
| Accounting year | applies_from_year, applies_to_year |
Select one | Every factor. See Reference year. |
| GWP set and horizon | gwp_method_native, gwp_horizon_years |
Select one | Several per factor on EXIOBASE |
| Characterization model | characterization_model (on emission_factor_value) |
Select one | Several per factor on EXIOBASE; see GWP for the rest |
| Price basis | price_basis, currency_year |
Select one | Spend factors: EXIOBASE (basic), Open CEDA (producer), USEEIO (purchaser and producer), ADEME |
| Grid mix | grid_mix |
Select one | Electricity: ADEME, AIB, DESNZ, EPA, MITECO, ÖKOBAUDAT |
| Calculation approach | calculation_approach |
Dual report: keep both, report apart | Scope 2 electricity, same libraries as grid mix |
| Radiative forcing | radiative_forcing |
Select one, and say which | Aviation: ADEME, DESNZ |
| EPD scenario and other qualifiers | value_qualifiers |
Select one | ÖKOBAUDAT |
| Supplier | supplier_code, supplier_name |
Descriptor, not an axis | ÖKOBAUDAT, MITECO |
| Representativeness | data_type |
Descriptor: specific, generic, average |
Every factor |
A dual report is still never a sum. The GHG Protocol asks for location-based and market-based Scope 2 side by side; each is one selected value.
Treatment route is not one of these axes. The landfill row and the recycling row for one waste material are separate factors, not two values of one factor, so no column in this table chooses between them. Waste treatment routes and the elected default explains which row the data elects when the route is unknown, and Which waste row to use when the route is unknown has the query.
Per library, how many top-level factors and rows the latest year holds, and how many factors carry each of the axes a value can vary on: grid mix, radiative forcing, price basis and qualifiers.
Show the SQL
SELECT f.library,
count(DISTINCT f.factor_id) AS factors,
count(*) AS values_in_latest_year,
count(DISTINCT f.factor_id) FILTER (WHERE f.grid_mix IS NOT NULL) AS with_grid_mix,
count(DISTINCT f.factor_id) FILTER (WHERE f.radiative_forcing IS NOT NULL) AS with_radiative_forcing,
count(DISTINCT f.factor_id) FILTER (WHERE f.price_basis IS NOT NULL) AS with_price_basis,
count(DISTINCT f.factor_id) FILTER (WHERE f.value_qualifiers IS NOT NULL) AS with_qualifiers
FROM open_ef.factors_flat f
WHERE f.library IN ('ademe','agribalyse','exiobase','desnz','miterd','aib','epa','useeio','okobaudat')
AND f.is_latest_activity_year
AND f.is_top_parent
GROUP BY 1
ORDER BY 1
| library | factors | values_in_latest_year | with_grid_mix | with_radiative_forcing | with_price_basis | with_qualifiers |
|---|---|---|---|---|---|---|
| ademe | 2767 | 2821 | 180 | 88 | 60 | 0 |
| agribalyse | 2451 | 2451 | 0 | 0 | 0 | 0 |
| aib | 34 | 130 | 34 | 0 | 0 | 0 |
| desnz | 1132 | 1132 | 76 | 18 | 0 | 0 |
| epa | 360 | 388 | 28 | 0 | 0 | 0 |
| exiobase | 8064 | 56448 | 0 | 0 | 8064 | 0 |
| miterd | 730 | 730 | 534 | 0 | 0 | 0 |
| okobaudat | 4189 | 4189 | 3 | 0 | 0 | 325 |
| useeio | 392 | 784 | 0 | 0 | 392 | 0 |
Open CEDA is left out of the query for speed: its 59,538 factors carry one value each, at producer price. Where values_in_latest_year exceeds factors, some factors have siblings; the sections below show each kind.
GWP characterizations: EXIOBASE#
EXIOBASE ships each sector's footprint under seven characterizations. The default is the AR5 100-year set; the other six stay available.
The methodologies one EXIOBASE factor is served on for its own accounting year, the default first, with the value on each.
Show the SQL
SELECT f.gwp_method_native, f.gwp_horizon_years, v.characterization_model, f.is_default_indicator,
round(f.value_co2e_native::numeric, 5) AS value_co2e_native
FROM open_ef.factors_flat f
JOIN open_ef.emission_factor_value v ON v.id = f.value_id
WHERE f.library = 'exiobase'
AND f.slug = 'ef-exiobase-animal_products_nec-fr-eur-cradle_to_gate-e2b36c2f'
AND f.applies_from_year = f.currency_year
ORDER BY f.is_default_indicator DESC, f.gwp_method_native, f.gwp_horizon_years, v.characterization_model
| gwp_method_native | gwp_horizon_years | characterization_model | is_default_indicator | value_co2e_native |
|---|---|---|---|---|
| ar5 | 100 | ipcc_ar5_direct | true | 3.76018 |
| ar4 | 20 | cml_1999 | false | 7.88503 |
| ar4 | 100 | cml_1999_baseline | false | 3.58586 |
| ar4 | 100 | cml_2001_baseline | false | 3.58583 |
| ar4 | 100 | houghton_net_max | false | 3.42572 |
| ar4 | 100 | houghton_net_min | false | 3.41286 |
| ar4 | 500 | cml_1999 | false | 1.53669 |
The 20-year value is about twice the 100-year one, because methane weighs far more over 20 years. None of the seven is wrong; they answer different questions, and an inventory uses one set throughout.
To select a sibling, replace is_default_indicator with the axis: AND f.gwp_horizon_years = 20.
Watch out. All seven rows are
unconverted: none is an AR6 number, and a total across libraries must leave them out or state the set it used. GWP explainsvalue_co2e_normalizedand when a row can be compared.
Price basis: USEEIO#
A spend factor means something only together with its currency year and its price basis. A purchaser price is what the buyer paid, trade and transport margins included; a producer price is what the maker received.
The two price bases of one USEEIO spend factor, purchaser (the default) and producer, with the value on each.
Show the SQL
SELECT f.price_basis, f.currency_year, f.is_default_indicator, f.unit_code,
round(f.value_co2e_native::numeric, 5) AS value_co2e_native
FROM open_ef.factors_flat f
WHERE f.library = 'useeio'
AND f.slug = 'ef-useeio-cheese_manufacturing-us-usd-cradle_to_gate-9c6d0a5a'
AND f.applies_from_year = f.currency_year
ORDER BY f.is_default_indicator DESC
| price_basis | currency_year | is_default_indicator | unit_code | value_co2e_native |
|---|---|---|---|---|
| purchaser | 2024 | true | usd | 1.00500 |
| producer | 2024 | false | usd | 0.97000 |
These are the published 2024-dollar numbers; the rows for other accounting years are re-priced from them. Use the purchaser row with an invoice amount. Use the producer row only when your spend is already at producer prices. Match a spend factor to your spend year covers currency_year and the re-pricing.
Grid mix and calculation approach#
A country's electricity factor carries one value per accounting mix. AIB's France factor has four, residual as the default: Guarantees you can rely on lists them. Select a mix with grid_mix, and a Scope 2 method with calculation_approach: location_based for the location-based total, market_based for the market-based one. Market-based vs location-based electricity says which library publishes which mix.
Radiative forcing#
For flights, ADEME publishes figures with and without the extra warming of non-CO2 effects at altitude: 44 factors each way. They are separate factors, not siblings, so every one is a default row. Choose one with radiative_forcing = 'with' or 'without', and never add a pair. DESNZ marks 18 factors with; its other flight factors leave the column NULL, which means not stated, not without.
EPD scenarios and other qualifiers#
value_qualifiers is a small jsonb bag on the value row, and it holds the discriminators that belong to one library family rather than to every factor. The keys are a closed registry of four, published in the code lists: scenario, lca_method, policy_year and preliminary. The loader rejects anything else, so the bag is an axis and not a dumping ground.
On ÖKOBAUDAT the key in use is scenario: the EN 15804 end-of-life and module D scenarios. Where a dataset prints several, they become sibling values under one factor, and they are far apart. This is the C4 row of one EPD, the disposal module, where the scenario decides what happens to the product at the end of its life.
The three end-of-life scenarios of one ÖKOBAUDAT product, the default first, and how many times the lowest each one is.
Show the SQL
SELECT f.value_qualifiers ->> 'scenario' AS scenario,
f.system_boundary,
f.is_default_indicator,
round(f.value_co2e_normalized::numeric, 5) AS kg_co2e_per_m2,
round((f.value_co2e_normalized / min(f.value_co2e_normalized) OVER ())::numeric, 1) AS times_the_lowest
FROM open_ef.factors_flat f
WHERE f.library = 'okobaudat'
AND f.slug = 'ef-okobaudat-floor_and_more_hollow-europe-m2-c4-fae39373'
AND f.is_latest_activity_year
ORDER BY f.is_default_indicator DESC, 4 DESC
| scenario | system_boundary | is_default_indicator | kg_co2e_per_m2 | times_the_lowest |
|---|---|---|---|---|
| S1 | C4 | true | 0.72168 | 22.9 |
| S2 | C4 | false | 0.04980 | 1.6 |
| S3 | C4 | false | 0.03147 | 1.0 |
The elected scenario is 22.9 times the lowest of the three, for the same square metre of the same product. They are alternatives: select one, never add them.
You usually do not have to choose. The import already elected a scenario for the default row, preferring the publisher's unnamed base scenario, then one the publisher named "standard", then S0, then the only one available, then the lowest numbered. To take another, drop is_default_indicator and name the scenario instead: AND f.value_qualifiers ->> 'scenario' = 'S2'.
The literals are the publisher's own strings, not a code list. S0 to S4 sit beside Standard scenario, Standard Szenario, standard scenario, Recycled, Landfill and Deponierung. Match case-insensitively, or lean on the default flag rather than on the text.
Watch out. A NULL bag does not mean the factor has no siblings. ÖKOBAUDAT writes its unnamed base scenario as NULL, and the import prefers that row over every named one, so the elected value can carry no qualifier while its alternatives do. It is not the common case: of the 469 ÖKOBAUDAT factors with more than one value row in the latest year, 442 have every row named, and 27 mix an unnamed row with named ones, the unnamed one elected in all 27. On
ef-okobaudat-circularly_recyclable-de-m2-d-0f71bbdfthe elected module D value is -0.03689 kg CO2e per m2, with S2 at -0.40990 and S3 at -0.49350 beside it. Count a factor's value rows to test for siblings, never the bag for NULL.
All 469 of those factors are module rows under a parent, never an EPD's own top row, so a query that walks a decomposition is where you meet them: A building product: modules and module D keeps is_default_indicator on the C modules and so takes the elected scenario of each without showing the others.
value_qualifiers is served on the factor detail response and shown as a chip on the factor page, and it is a column on factors_flat. It is not a filter on the API and not a factor search facet, and the Columns menu does not offer it, though an export asked for over the API can name it. Filtering to a named scenario is a SQL operation either way.
Gases and carbon origin#
The per-gas and per-carbon-origin columns are not an axis: they are components of the one headline on the same row. Read them with the NULL-versus-zero rule in How factors are cleaned, and never rebuild the headline from them.