1. Why this notebook exists…

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.

2. Growth-marketing instincts: get some numbers on the page

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()

3. Communications instincts: collect the governance language

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…

4. R instincts: a toy portfolio steering picture

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()

5. Text and anthropology instincts: looking at how banks talk

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()

6. Where this sits in my bigger story

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. :)