Adjustment Functions¶
Functions for calculating pre-allocation responsibility, capability, and Gini adjustments.
Relative Adjustments¶
calculate_relative_adjustment¶
fair_shares.library.utils.calculate_relative_adjustment ¶
calculate_relative_adjustment(
values: TimeseriesDataFrame | Series,
functional_form: str = "asinh",
exponent: float = 1.0,
inverse: bool = True,
normalize: bool = True,
) -> TimeseriesDataFrame | Series
Calculate relative adjustment factors for allocations.
Applies a transformation to input values (e.g., GDP per capita, cumulative emissions) to produce adjustment factors. See docs/science/allocations.md for theoretical grounding.
When normalize=True (default), values are divided by their median before
transformation. This ensures unit invariance: multiplying all inputs by a
constant (e.g., converting USD to EUR) produces identical adjustment factors,
because the constant cancels in the ratio x / median(x).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
values
|
TimeseriesDataFrame | Series
|
Input values (GDP per capita, cumulative emissions, etc.) |
required |
functional_form
|
str
|
Transformation to apply. Default is |
'asinh'
|
exponent
|
float
|
Controls how aggressively the adjustment squashes the range.
With |
1.0
|
inverse
|
bool
|
If True (default), higher values -> lower relative adjustment factor. If False, higher values -> higher relative adjustment factor. |
True
|
normalize
|
bool
|
If True (default), divide values by their median before transformation to achieve unit invariance. Set to False for legacy behaviour or when inputs are already dimensionless. |
True
|
Returns:
| Type | Description |
|---|---|
Adjustment factors with same structure as input
|
|
Notes
This function operationalizes both the Polluter Pays Principle (via historical responsibility adjustments over the window prior to the allocation year) and the Ability to Pay Principle (via economic capability adjustments, from the allocation year onwards).
The arcsinh function itself is defined on the full real line and preserves
sign (it is odd), so negative inputs map to negative transformed values and
zero maps to zero. However, the subsequent exponentiation step
arcsinh(x) ** (sign * exponent) is not closed over the reals: for a
non-integer real exponent (the typical case, since inverse=True is the
default), numpy does not promote to complex, so negative bases yield NaN
and a zero base with a negative exponent yields inf. In other words,
asinh applies no clamping — callers that may pass negative values (e.g.
cumulative CO2 including LULUCF sinks) or exact zeros must handle the sign
upstream, either by flooring inputs at a small positive value or by using
an emission basis that cannot be negative (e.g. fossil-fuel-and-industry
only). The power form clamps to a small epsilon (1e-10) for numerical
safety with negative exponents.
Gini Adjustments¶
calculate_gini_adjusted_gdp¶
fair_shares.library.utils.calculate_gini_adjusted_gdp ¶
calculate_gini_adjusted_gdp(
total_gdps: ndarray,
gini_coefficients: ndarray,
income_floor: float,
total_populations: ndarray,
max_adjustment: float = 0.8,
) -> ndarray
Gini-adjusted GDP (capability) using the GDR development threshold.
Implements an interpretation of the Greenhouse Development Rights (GDR) framework's capability metric for entitlement allocation. Note: GDR was originally designed for burden-sharing; fair-shares adapts its capability calculation for use in an entitlement context. Only income above a development threshold counts as "ability to pay" for climate action.
For each individual, their first income_floor of annual income is exempt —
it's needed for basic human development. Only the excess above the floor
contributes to national capability.
Mathematical Foundation
Income is modelled as log-normal, parameterised by the Gini coefficient \(G\):
The proportion of the population below the floor is:
The income share of people below the floor (Lorenz curve) is:
National capability (aggregate above-threshold income):
Where \(N\) is the total population.
Effect of Inequality
When combined with an income floor, higher Gini always increases measured capability: inequality concentrates income in the upper tail, so more national income sits above the development threshold:
| Scenario (floor = $7,500/yr) | Gini 0.30 | Gini 0.60 | Direction |
|---|---|---|---|
| Rich (mean $20k) | 63% of GDP | 70% of GDP | ↑ moderate |
| Poor (mean $3k) | 1.6% of GDP | 21.5% of GDP | ↑ dramatic |
For poor countries, inequality is the only mechanism that creates any above-threshold income at all. At perfect equality with mean $3k, nobody exceeds $7,500 so capability is near zero.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
total_gdps
|
ndarray
|
Array of total GDP values for each country. |
required |
gini_coefficients
|
ndarray
|
Array of Gini coefficients (0-1) for each country. |
required |
income_floor
|
float
|
Development threshold in currency units per capita per year.
Must use the price base of |
required |
total_populations
|
ndarray
|
Array of total population values for each country. |
required |
max_adjustment
|
float
|
Maximum adjustment allowed as proportion of total GDP (default: 0.8). Prevents extreme reductions for countries with very high inequality. Note: with the GDR formula, higher inequality actually increases capability; extreme reductions are more likely for low-income, low-inequality countries where most people are near the threshold. |
0.8
|
Returns:
| Type | Description |
|---|---|
ndarray
|
Array of adjusted GDP values (capability) for each country. |
apply_gini_adjustment¶
fair_shares.library.utils.apply_gini_adjustment ¶
apply_gini_adjustment(
gdp_data: TimeseriesDataFrame | Series,
population_data: TimeseriesDataFrame | Series,
gini_lookup: dict[str, float],
income_floor: float,
max_gini_adjustment: float,
group_level: str = "iso3c",
) -> TimeseriesDataFrame | Series
Apply Gini adjustment to GDP data for all groups.
Wrapper that applies calculate_gini_adjusted_gdp across all countries
in a DataFrame or Series, handling MultiIndex grouping and Gini lookup.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
gdp_data
|
TimeseriesDataFrame | Series
|
GDP data (DataFrame or Series) |
required |
population_data
|
TimeseriesDataFrame | Series
|
Population data (DataFrame or Series) |
required |
gini_lookup
|
dict[str, float]
|
Dictionary mapping country codes to Gini coefficients |
required |
income_floor
|
float
|
Income floor value |
required |
max_gini_adjustment
|
float
|
Maximum adjustment allowed as proportion of total GDP |
required |
group_level
|
str
|
Level name for grouping (typically "iso3c") |
'iso3c'
|
Returns:
| Type | Description |
|---|---|
Gini-adjusted GDP data with same structure as input
|
|
create_gini_lookup_dict¶
fair_shares.library.utils.create_gini_lookup_dict ¶
Create a simple lookup dict for Gini coefficients.
Assumes the common case: - Index: MultiIndex with level 'iso3c' (and possibly 'unit') - Column: 'gini'
Falls back to using 'iso3c' as a column if not found in the index.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
gini_data_df
|
TimeseriesDataFrame
|
DataFrame containing Gini coefficient data |
required |
Returns:
| Type | Description |
|---|---|
Dictionary mapping country codes to Gini coefficients
|
|
Deviation Constraints¶
apply_deviation_constraint¶
fair_shares.library.utils.apply_deviation_constraint ¶
apply_deviation_constraint(
shares: TimeseriesDataFrame,
population: TimeseriesDataFrame,
max_deviation_sigma: float,
group_level: str,
) -> TimeseriesDataFrame
Apply maximum deviation constraint from equal per capita baseline.
Constrains allocation shares to within a specified number of standard deviations from equal per capita distribution. See docs/science/allocations.md for theoretical basis.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
shares
|
TimeseriesDataFrame
|
Current allocation shares |
required |
population
|
TimeseriesDataFrame
|
Population data |
required |
max_deviation_sigma
|
float
|
Maximum allowed deviation in standard deviations |
required |
group_level
|
str
|
Level name for grouping (typically "iso3c") |
required |
Returns:
| Type | Description |
|---|---|
Constrained allocation shares
|
|
See Also¶
- Core Utilities: Data manipulation functions
- Budget Allocations: Functions that use these adjustments
- Pathway Allocations: Functions that use these adjustments