Python packages / tossd-reader / How-to guides
Analyse financial instruments and concessionality
Evaluate debt vulnerabilities and financing terms by disaggregating flows across instrument categories (grants, concessional loans, non-concessional loans, and equity) and calculating net resource transfers after debt repayments.
Steps
-
Query activity records and classify instruments. The
add_instrument_group()method requiresfinance_instrument_codeandconcessionality_flag, both available in the"analysis"preset.import tossd_reader as tossd df = tossd.get_tossd(years=2024, columns="analysis", units="usd_million") ig = df.tossd.add_instrument_group()The debt-instrument code family (
420-425,4221, and4222) splits into"Concessional Loans"and"Non-concessional Loans"byconcessionality_flag:1indicates concessional terms and0indicates non-concessional terms. All other categories ("Grants","Equity","Guarantees","Hybrid/Mezzanine","Direct Provider Spending","Subsidies", and"Other Instruments") are mapped directly fromfinance_instrument_code. -
Aggregate disbursements by instrument group. Retain unclassified rows by specifying
dropna=False.ig.groupby("instrument_group", dropna=False, observed=True)[ "usd_disbursement" ].sum().round(1)Concessional Loans 47194.6 Direct Provider Spending 49378.8 Equity 2796.1 Grants 200931.0 Guarantees 882.3 Hybrid/Mezzanine 467.2 Non-concessional Loans 95923.0 Other Instruments 8.7 NaN 100094.2The
NaNbucket represents approximately 20% of 2024 disbursements. It combines pseudo-aggregate rows retained byget_tossd()by default (provider_code == 0, which lack individualfinance_instrument_codevalues) and debt records with blankconcessionality_flagfields that cannot be assigned to concessional or non-concessional groups. Standard pandasgroupbyoperations dropNaNkeys by default. Specifydropna=Falseor exclude aggregate rows before grouping. -
Exclude aggregate rows to isolate unclassified residuals.
ex = df.tossd.exclude_aggregates() ig2 = ex.tossd.add_instrument_group() ig2.groupby("instrument_group", dropna=False, observed=True)[ "usd_disbursement" ].sum().round(1)Concessional Loans 47194.6 Direct Provider Spending 49378.8 Equity 2796.1 Grants 200931.0 Guarantees 882.3 Hybrid/Mezzanine 467.2 Non-concessional Loans 95923.0 Other Instruments 8.7 NaN 714.6Excluding aggregates removes the pseudo-aggregate component of
NaN. The remaining USD 714.6 million (approximately 0.2% of the total) consists entirely of debt rows with blankconcessionality_flagvalues. Settingdropna=Falsesurfaces this residual in summary tables. -
Calculate net resource transfers after debt repayments. Subtract
usd_reflow(principal repayments and capital reflows returned to providers) fromusd_disbursementto determine net financial transfers. Filter to Pillar I activities before calculating net resource flows.p1 = tossd.get_tossd(years=2024, pillars=1, columns="analysis", units="usd_million") p1 = p1.tossd.exclude_aggregates().tossd.add_instrument_group() summary = ( p1.groupby("instrument_group", dropna=False, observed=True)[ ["usd_disbursement", "usd_reflow"] ] .sum() .reset_index() ) summary["net_disbursement"] = summary["usd_disbursement"] - summary["usd_reflow"] summary["share_of_gross_pct"] = ( summary["usd_disbursement"] / summary["usd_disbursement"].sum() * 100 ).round(1) print(summary.round(1).to_string(index=False))instrument_group usd_disbursement usd_reflow net_disbursement share_of_gross_pct Concessional Loans 47086.4 16356.6 30729.8 17.0 Direct Provider Spending 13163.5 309.9 12853.7 4.8 Equity 2790.5 1314.7 1475.8 1.0 Grants 116268.9 1973.2 114295.7 42.0 Guarantees 882.2 859.3 22.9 0.3 Hybrid/Mezzanine 466.3 196.2 270.0 0.2 Non-concessional Loans 95190.0 52531.5 42658.5 34.4 Other Instruments 2.9 0.0 2.9 0.0 NaN 714.6 535.7 178.9 0.3Published records include small reflow entries against grants (USD 2.0 billion of USD 116.3 billion in 2024, or under 2%). Verify grant net disbursements directly, since reflows make gross and net figures differ.
-
Verify the classification vintage before publishing figures.
tossd.get_instrument_groups_version()'oecd-dac-cl15-2026-09-01/instrument-groups-methodology-v2'This stamp identifies the OECD DAC "List 15: Type of finance" source date alongside the project's methodology revision. A
finance_instrument_codenot present in the packaged table raisesUnknownCodeErrorto prevent unrecognised codes from being grouped into"Other Instruments"unnoticed.
Verify it worked
Confirm that the dropna=False aggregation matches the frame's total disbursement, and compare against a default groupby result.
with_na = ig.groupby("instrument_group", dropna=False, observed=True)[
"usd_disbursement"
].sum()
print(round(with_na.sum(), 1) == round(ig["usd_disbursement"].sum(), 1))
True
default = ig.groupby("instrument_group", observed=True)["usd_disbursement"].sum()
print(round(default.sum(), 1))
397581.8
Default groupby behaviour drops the USD 100.1 billion NaN bucket entirely, producing USD 397,581.8 million instead of the full USD 497,676.0 million total.
Troubleshooting
-
ValueErroronadd_instrument_group()naming missing columns. The DataFrame was queried withcolumns="minimal"or a list missingfinance_instrument_codeorconcessionality_flag. Re-query withcolumns="analysis".m = tossd.get_tossd(years=2024, columns="minimal", units="usd_million") m.tossd.add_instrument_group()ValueError: add_instrument_group() needs column(s) finance_instrument_code, concessionality_flag, not present in df. Re-query with columns='analysis', or add finance_instrument_code, concessionality_flag to your columns= list. -
UnknownCodeErroron afinance_instrument_codevalue. A TOSSD vintage newer than the packaged snapshot contains a code with no mapping. The helper raises an error to ensure new instruments are handled explicitly. Checktossd.get_instrument_groups_version()against the active data vintage, and refresh packaged codelists if necessary.
See also
- About the amount columns for
usd_disbursement,usd_reflow, and financial metrics. - Pillars and aggregate rows for the concessionality benchmark (35% grant element, 5% discount rate) implemented by
concessionality_flag. - Helpers reference for
add_instrument_group()parameters and return contracts.