Because I didn’t start in sustainable finance.
My career started in growth marketing:
Then, I moved into institutional communications:
Along the way, I picked up R and data from my master’s (hello and thank you, Prof. Marcin Szymkowiak) as a way to take this more seriously:
This notebook is a small, intended-to-be reproducible slice of that arc applied to sustainable finance. This uses R to structure and visualise a few things from two bank climate-risk reports, that apparently changed how I think:
Please not it is not a full model. I intended this as a way of making the story legible in numbers and code. Let’s buckle up.
Growth marketing taught me that if you care about something, you write down the numbers first. Having drilled myself into that mentality deep and long enough already, I applied the same instinct here by hand-building a tiny table of climate-finance metrics from ING and Mandiri.
bank_metrics <- tribble(
~bank, ~metric, ~value, ~unit, ~year,
"ING", "Renewables financing commitment", 7.5, "EUR bn/year", 2025,
"ING", "Renewables financing in 2024", 7.0, "EUR bn", 2024,
"ING", "Sustainable finance mobilised", 130, "EUR bn", 2024,
"ING", "Sustainable finance target", 150, "EUR bn/year", 2027,
"Mandiri", "NZE operations target year", 2030, "year", NA,
"Mandiri", "NZE financing target year", 2060, "year", NA
)
bank_metrics
## # A tibble: 6 × 5
## bank metric value unit year
## <chr> <chr> <dbl> <chr> <dbl>
## 1 ING Renewables financing commitment 7.5 EUR bn/year 2025
## 2 ING Renewables financing in 2024 7 EUR bn 2024
## 3 ING Sustainable finance mobilised 130 EUR bn 2024
## 4 ING Sustainable finance target 150 EUR bn/year 2027
## 5 Mandiri NZE operations target year 2030 year NA
## 6 Mandiri NZE financing target year 2060 year NA
bank_metrics %>%
filter(unit %in% c("EUR bn/year", "EUR bn")) %>%
ggplot(aes(x = metric, y = value, fill = bank)) +
geom_col(position = "dodge") +
coord_flip() +
labs(
title = "Selected climate-finance metrics (ING vs Mandiri)",
x = "",
y = "Value"
) +
theme_minimal()
My communications work has been training me to care about who speaks and how they frame things. So, I pulled out a few governance and process phrases from the reports. Then I encoded them as a tiny dataset.
governance_terms <- tribble(
~bank, ~category, ~term,
"ING", "Targets", "SBTi-validated 1.5°C-aligned targets for operations and portfolio",
"ING", "Portfolio", "Terra approach for sector-level net-zero alignment",
"ING", "Clients", "Client Transition Plan (CTP) scores via ESG.X and public disclosures",
"ING", "Alliances", "Net-Zero Banking Alliance, Principles for Responsible Banking, PCAF",
"Mandiri", "Risk framework", "Three Lines of Defense plus 1.5 line (fraud and senior operational risk)",
"Mandiri", "Committees", "Risk Management Committee (RMC), Risk Oversight Committee (KPR)",
"Mandiri", "ESG unit", "ESG Group under Vice President Director (comms, policy, operations, product/portfolio)",
"Mandiri", "Processes", "ESRM, Industry Acceptance Criteria (IAC), OJK CRMS pilots, TKBI implementation"
)
governance_terms
## # A tibble: 8 × 3
## bank category term
## <chr> <chr> <chr>
## 1 ING Targets SBTi-validated 1.5°C-aligned targets for operations an…
## 2 ING Portfolio Terra approach for sector-level net-zero alignment
## 3 ING Clients Client Transition Plan (CTP) scores via ESG.X and publ…
## 4 ING Alliances Net-Zero Banking Alliance, Principles for Responsible …
## 5 Mandiri Risk framework Three Lines of Defense plus 1.5 line (fraud and senior…
## 6 Mandiri Committees Risk Management Committee (RMC), Risk Oversight Commit…
## 7 Mandiri ESG unit ESG Group under Vice President Director (comms, policy…
## 8 Mandiri Processes ESRM, Industry Acceptance Criteria (IAC), OJK CRMS pil…
The R audits I did for the institutions where I was managing and involved in their social media - therefore the quantified metrics - were about separating spikes from structure. Seeing if pattern of what works hold and why not. Here, I wanted a simple way to illustrate what “driving down emissions” and “building up a sustainable future” could look like in a lending portfolio.
toy_portfolio <- tribble(
~sector, ~loan_exposure_eur_bn, ~emissions_intensity_tCO2_per_eur_m,
"Fossil fuels", 10, 0.80,
"Power generation", 8, 0.40,
"Renewables", 3, 0.05,
"Residential RE", 6, 0.20
)
toy_portfolio <- toy_portfolio %>%
mutate(financed_emissions_tCO2 = loan_exposure_eur_bn * 1000 * emissions_intensity_tCO2_per_eur_m)
toy_portfolio
## # A tibble: 4 × 4
## sector loan_exposure_eur_bn emissions_intensity_…¹ financed_emissions_t…²
## <chr> <dbl> <dbl> <dbl>
## 1 Fossil fue… 10 0.8 8000
## 2 Power gene… 8 0.4 3200
## 3 Renewables 3 0.05 150
## 4 Residentia… 6 0.2 1200
## # ℹ abbreviated names: ¹emissions_intensity_tCO2_per_eur_m,
## # ²financed_emissions_tCO2
transition_scenario <- toy_portfolio %>%
mutate(
loan_exposure_eur_bn_new = case_when(
sector == "Fossil fuels" ~ 6,
sector == "Renewables" ~ 7,
TRUE ~ loan_exposure_eur_bn
),
financed_emissions_tCO2_new = loan_exposure_eur_bn_new * 1000 * emissions_intensity_tCO2_per_eur_m
)
transition_scenario
## # A tibble: 4 × 6
## sector loan_exposure_eur_bn emissions_intensity_…¹ financed_emissions_t…²
## <chr> <dbl> <dbl> <dbl>
## 1 Fossil fue… 10 0.8 8000
## 2 Power gene… 8 0.4 3200
## 3 Renewables 3 0.05 150
## 4 Residentia… 6 0.2 1200
## # ℹ abbreviated names: ¹emissions_intensity_tCO2_per_eur_m,
## # ²financed_emissions_tCO2
## # ℹ 2 more variables: loan_exposure_eur_bn_new <dbl>,
## # financed_emissions_tCO2_new <dbl>
transition_scenario %>%
select(sector, financed_emissions_tCO2, financed_emissions_tCO2_new) %>%
pivot_longer(cols = starts_with("financed"), names_to = "scenario", values_to = "emissions") %>%
mutate(scenario = ifelse(grepl("new", scenario), "After rebalancing", "Baseline")) %>%
ggplot(aes(x = sector, y = emissions, fill = scenario)) +
geom_col(position = "dodge") +
coord_flip() +
labs(
title = "Toy financed-emissions change from simple portfolio rebalancing",
x = "",
y = "Financed emissions (tCO2)"
) +
theme_minimal()
My BA in social anthropology has trained me to listen for how institutions describe themselves, their own version of legitimacy in the world. Words are vehicle to express it. Which words they use for risk, responsibility, and agency? With R, I can do a light version of that on bank climate-risk text.
# Representative climate-governance excerpts (shortened for illustration)
ing_text <- "At ING it is our ambition to play a leading role in accelerating the transition to a low-carbon economy. Terra is our global climate mitigation approach that informs how we steer the most carbon-intensive parts of our lending portfolio towards net zero by 2050. We use sector-level pathways, client transition plans and science-based targets validated by SBTi to align our portfolio with global climate goals."
mandiri_text <- "Bank Mandiri identifies climate and environmental risk as an emerging risk that is cross-cutting in nature and may affect the Bank's overall risk profile, particularly credit, market, operational, legal and reputational risk. Climate Risk Management and Scenario Analysis (CRMS) is implemented in line with OJK guidance, integrating ESG risk into the Risk Management Policy and Enterprise Risk Management framework through the Three Lines of Defense, ESRM and Industry Acceptance Criteria."
texts <- tibble(
bank = c("ING", "Mandiri"),
text = c(ing_text, mandiri_text)
)
texts
## # A tibble: 2 × 2
## bank text
## <chr> <chr>
## 1 ING At ING it is our ambition to play a leading role in accelerating the …
## 2 Mandiri Bank Mandiri identifies climate and environmental risk as an emerging…
word_counts <- texts %>%
unnest_tokens(word, text) %>%
filter(!word %in% stop_words$word) %>%
count(bank, word, sort = TRUE)
word_counts %>%
group_by(bank) %>%
slice_head(n = 15)
## # A tibble: 30 × 3
## # Groups: bank [2]
## bank word n
## <chr> <chr> <int>
## 1 ING carbon 2
## 2 ING climate 2
## 3 ING global 2
## 4 ING portfolio 2
## 5 ING transition 2
## 6 ING 2050 1
## 7 ING accelerating 1
## 8 ING align 1
## 9 ING ambition 1
## 10 ING approach 1
## # ℹ 20 more rows
theme_lexicon <- tribble(
~word, ~theme,
"risk", "Risk & governance",
"emerging", "Risk & governance",
"profile", "Risk & governance",
"credit", "Risk & governance",
"market", "Risk & governance",
"operational", "Risk & governance",
"terra", "Steering & tools",
"portfolio", "Steering & tools",
"targets", "Steering & tools",
"sbtI", "Steering & tools",
"transition", "Transition",
"net", "Transition",
"zero", "Transition",
"crms", "Processes",
"framework", "Processes",
"defense", "Processes",
"criteria", "Processes"
)
word_themes <- word_counts %>%
inner_join(theme_lexicon, by = "word")
word_themes
## # A tibble: 15 × 4
## bank word n theme
## <chr> <chr> <int> <chr>
## 1 Mandiri risk 8 Risk & governance
## 2 ING portfolio 2 Steering & tools
## 3 ING transition 2 Transition
## 4 ING net 1 Transition
## 5 ING targets 1 Steering & tools
## 6 ING terra 1 Steering & tools
## 7 Mandiri credit 1 Risk & governance
## 8 Mandiri criteria 1 Processes
## 9 Mandiri crms 1 Processes
## 10 Mandiri defense 1 Processes
## 11 Mandiri emerging 1 Risk & governance
## 12 Mandiri framework 1 Processes
## 13 Mandiri market 1 Risk & governance
## 14 Mandiri operational 1 Risk & governance
## 15 Mandiri profile 1 Risk & governance
word_themes %>%
ggplot(aes(x = theme, y = n, fill = bank)) +
geom_col(position = "dodge") +
labs(
title = "Tiny thematic snapshot of ING vs Mandiri climate language",
x = "Theme",
y = "Count (in sample excerpts)"
) +
theme_minimal()
Putting it all together, this notebook is a mirror of my very own humble arc:
This document is not meant to be exhaustive, it is here so that when I talk about sustainable finance and climate risk, I can point to a small, honest object that shows how I actually think - narrative first, numbers close behind, code as a way of keeping myself honest (and accountable).
Thank you for reading. :)