{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "f72d13ba",
   "metadata": {},
   "source": [
    "# Behavioural diagnostic of a digital savings behaviour\n",
    "\n",
    "**Worked example on synthetic data, by Ahmed Beddi.** No real provider, programme, market or person is described. Every probability and every barrier score below is an assumption chosen to illustrate the method.\n",
    "\n",
    "**Target behaviour.** Adults who already hold an active mobile-money wallet make at least one deposit into its savings feature each calendar month.\n",
    "\n",
    "This notebook\n",
    "1. generates a seeded synthetic event log (mulberry32 PRNG, seed 20261103, 20,000 wallet holders);\n",
    "2. computes the journey funnel *aware → intend → initiate → complete → repeat*, overall and by segment;\n",
    "3. scores and ranks 14 candidate barriers with $\\text{score} = P^{w_P} S^{w_S} T^{w_T}$ (defaults $w = 1$);\n",
    "4. groups the top barriers by COM-B component and by the intervention package they point to;\n",
    "5. writes the barrier register (EN and FR CSV).\n",
    "\n",
    "It mirrors the interactive demo on the website (`components/demos/lib/behaviouralDiagnostic.ts`): same PRNG, same draw order, same probabilities, same scores and tie-breaks. The last cell checks the headline numbers against the demo defaults."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "accb0291",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-11-03T16:08:22.319637Z",
     "iopub.status.busy": "2026-11-03T16:08:22.319385Z",
     "iopub.status.idle": "2026-11-03T16:08:22.562618Z",
     "shell.execute_reply": "2026-11-03T16:08:22.561517Z"
    }
   },
   "outputs": [],
   "source": [
    "import math\n",
    "\n",
    "import pandas as pd\n",
    "\n",
    "SEED, N_USERS = 20261103, 20_000\n",
    "STEPS = [\"aware\", \"intend\", \"initiate\", \"complete\", \"repeat\"]\n",
    "M32 = 0xFFFFFFFF\n",
    "\n",
    "\n",
    "def _imul(a, b):\n",
    "    r = (a * b) & M32\n",
    "    return r - (1 << 32) if r & 0x80000000 else r\n",
    "\n",
    "\n",
    "def _i32(x):\n",
    "    x &= M32\n",
    "    return x - (1 << 32) if x & 0x80000000 else x\n",
    "\n",
    "\n",
    "def mulberry32(a):\n",
    "    state = [_i32(a)]\n",
    "\n",
    "    def rand():\n",
    "        a = _i32(state[0] + 0x6D2B79F5)\n",
    "        state[0] = a\n",
    "        t = _imul(a ^ ((a & M32) >> 15), 1 | a)\n",
    "        t = _i32(_i32(t + _imul(t ^ ((t & M32) >> 7), 61 | t)) ^ t)\n",
    "        return ((t ^ ((t & M32) >> 14)) & M32) / 4294967296\n",
    "\n",
    "    return rand"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "25411e53",
   "metadata": {},
   "source": [
    "## 1. Synthetic event log\n",
    "\n",
    "Each wallet holder consumes exactly seven draws: sex, area, then one draw per journey step. A holder reaches a step only if she reached the previous one. In a real diagnostic, *aware* and *intend* come from a short survey linked to the account (with consent); *initiate* from USSD or app session logs (the savings deposit flow is opened); *complete* and *repeat* from the transaction log (a customer-initiated transfer into the savings feature in month 1, and again in month 2)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "25959a68",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-11-03T16:08:22.565919Z",
     "iopub.status.busy": "2026-11-03T16:08:22.565655Z",
     "iopub.status.idle": "2026-11-03T16:08:22.579870Z",
     "shell.execute_reply": "2026-11-03T16:08:22.578813Z"
    }
   },
   "outputs": [],
   "source": [
    "# Step-conversion probabilities of the synthetic population (assumptions, not estimates).\n",
    "# Each user consumes exactly 7 draws, in this order: sex, area, aware, intend, initiate, complete, repeat.\n",
    "P_FEMALE, P_RURAL = 0.48, 0.42\n",
    "\n",
    "\n",
    "def step_probs(female, rural):\n",
    "    return {\n",
    "        \"aware\": 0.78 - 0.10 * rural,          # knows the savings feature exists (survey module)\n",
    "        \"intend\": 0.62 - 0.04 * female,        # plans to deposit this month, given aware (survey module)\n",
    "        \"initiate\": 0.55 - 0.08 * rural,       # opens the savings deposit flow, given intend (session log)\n",
    "        \"complete\": 0.70 - 0.10 * rural,       # deposit confirmed in month 1, given initiate (transaction log)\n",
    "        \"repeat\": 0.48,                        # deposits again in month 2, given complete (transaction log)\n",
    "    }\n",
    "\n",
    "\n",
    "def simulate(seed=SEED, n=N_USERS):\n",
    "    \"\"\"Return users (one row each) and the event log (one row per event).\"\"\"\n",
    "    u = mulberry32(seed)\n",
    "    users, events = [], []\n",
    "    for i in range(n):\n",
    "        female = 1 if u() < P_FEMALE else 0\n",
    "        rural = 1 if u() < P_RURAL else 0\n",
    "        p = step_probs(female, rural)\n",
    "        draws = [u() for _ in STEPS]          # always 5 draws, whatever the path\n",
    "        reached, alive = {}, True\n",
    "        for s, d in zip(STEPS, draws):\n",
    "            alive = alive and d < p[s]\n",
    "            reached[s] = int(alive)\n",
    "        uid = f\"U{i + 1:05d}\"\n",
    "        users.append({\"user_id\": uid, \"sex\": \"F\" if female else \"M\", \"area\": \"rural\" if rural else \"urban\", **reached})\n",
    "        source = {\"aware\": \"survey\", \"intend\": \"survey\", \"initiate\": \"session_log\", \"complete\": \"transaction_log\", \"repeat\": \"transaction_log\"}\n",
    "        month = {\"aware\": 1, \"intend\": 1, \"initiate\": 1, \"complete\": 1, \"repeat\": 2}\n",
    "        for s in STEPS:\n",
    "            if reached[s]:\n",
    "                events.append({\"user_id\": uid, \"event\": s, \"month\": month[s], \"source\": source[s]})\n",
    "    return pd.DataFrame(users), pd.DataFrame(events)\n",
    "\n",
    "\n",
    "def funnel(users, events, mask=None):\n",
    "    ids = users[\"user_id\"] if mask is None else users.loc[mask, \"user_id\"]\n",
    "    ev = events[events[\"user_id\"].isin(set(ids))]\n",
    "    base = len(ids)\n",
    "    counts = [base] + [ev.loc[ev[\"event\"] == s, \"user_id\"].nunique() for s in STEPS]\n",
    "    rows = []\n",
    "    for k, s in enumerate(STEPS):\n",
    "        prev, cur = counts[k], counts[k + 1]\n",
    "        rows.append({\"step\": s, \"users\": cur, \"pct_of_base\": 100 * cur / base,\n",
    "                     \"conversion_from_previous\": 100 * cur / prev if prev else float(\"nan\"),\n",
    "                     \"drop_off\": prev - cur})\n",
    "    return base, pd.DataFrame(rows)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "8700714b",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-11-03T16:08:22.582028Z",
     "iopub.status.busy": "2026-11-03T16:08:22.581839Z",
     "iopub.status.idle": "2026-11-03T16:08:22.926711Z",
     "shell.execute_reply": "2026-11-03T16:08:22.924357Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "20,000 wallet holders, 32,940 events\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>user_id</th>\n",
       "      <th>event</th>\n",
       "      <th>month</th>\n",
       "      <th>source</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>U00001</td>\n",
       "      <td>aware</td>\n",
       "      <td>1</td>\n",
       "      <td>survey</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>U00001</td>\n",
       "      <td>intend</td>\n",
       "      <td>1</td>\n",
       "      <td>survey</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>U00001</td>\n",
       "      <td>initiate</td>\n",
       "      <td>1</td>\n",
       "      <td>session_log</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>U00002</td>\n",
       "      <td>aware</td>\n",
       "      <td>1</td>\n",
       "      <td>survey</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>U00003</td>\n",
       "      <td>aware</td>\n",
       "      <td>1</td>\n",
       "      <td>survey</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>U00004</td>\n",
       "      <td>aware</td>\n",
       "      <td>1</td>\n",
       "      <td>survey</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>U00004</td>\n",
       "      <td>intend</td>\n",
       "      <td>1</td>\n",
       "      <td>survey</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>U00004</td>\n",
       "      <td>initiate</td>\n",
       "      <td>1</td>\n",
       "      <td>session_log</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  user_id     event  month       source\n",
       "0  U00001     aware      1       survey\n",
       "1  U00001    intend      1       survey\n",
       "2  U00001  initiate      1  session_log\n",
       "3  U00002     aware      1       survey\n",
       "4  U00003     aware      1       survey\n",
       "5  U00004     aware      1       survey\n",
       "6  U00004    intend      1       survey\n",
       "7  U00004  initiate      1  session_log"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "users, events = simulate()\n",
    "print(f\"{len(users):,} wallet holders, {len(events):,} events\")\n",
    "events.head(8)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "20cdcb75",
   "metadata": {},
   "source": [
    "## 2. Funnel"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "5330a5c5",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-11-03T16:08:22.928951Z",
     "iopub.status.busy": "2026-11-03T16:08:22.928697Z",
     "iopub.status.idle": "2026-11-03T16:08:22.975686Z",
     "shell.execute_reply": "2026-11-03T16:08:22.974291Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Eligible wallet holders: 20,000\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>step</th>\n",
       "      <th>users</th>\n",
       "      <th>pct_of_base</th>\n",
       "      <th>conversion_from_previous</th>\n",
       "      <th>drop_off</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>aware</td>\n",
       "      <td>14776</td>\n",
       "      <td>73.9</td>\n",
       "      <td>73.9</td>\n",
       "      <td>5224</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>intend</td>\n",
       "      <td>8950</td>\n",
       "      <td>44.8</td>\n",
       "      <td>60.6</td>\n",
       "      <td>5826</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>initiate</td>\n",
       "      <td>4639</td>\n",
       "      <td>23.2</td>\n",
       "      <td>51.8</td>\n",
       "      <td>4311</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>complete</td>\n",
       "      <td>3093</td>\n",
       "      <td>15.5</td>\n",
       "      <td>66.7</td>\n",
       "      <td>1546</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>repeat</td>\n",
       "      <td>1482</td>\n",
       "      <td>7.4</td>\n",
       "      <td>47.9</td>\n",
       "      <td>1611</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "       step  users  pct_of_base  conversion_from_previous  drop_off\n",
       "0     aware  14776         73.9                      73.9      5224\n",
       "1    intend   8950         44.8                      60.6      5826\n",
       "2  initiate   4639         23.2                      51.8      4311\n",
       "3  complete   3093         15.5                      66.7      1546\n",
       "4    repeat   1482          7.4                      47.9      1611"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "base, f = funnel(users, events)\n",
    "print(f\"Eligible wallet holders: {base:,}\")\n",
    "f.round(1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "b9560938",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-11-03T16:08:22.977792Z",
     "iopub.status.busy": "2026-11-03T16:08:22.977549Z",
     "iopub.status.idle": "2026-11-03T16:08:23.099798Z",
     "shell.execute_reply": "2026-11-03T16:08:23.098220Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>n</th>\n",
       "      <th>aware</th>\n",
       "      <th>intend</th>\n",
       "      <th>initiate</th>\n",
       "      <th>complete</th>\n",
       "      <th>repeat</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>segment</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>all</th>\n",
       "      <td>20000</td>\n",
       "      <td>73.9</td>\n",
       "      <td>44.8</td>\n",
       "      <td>23.2</td>\n",
       "      <td>15.5</td>\n",
       "      <td>7.4</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>women</th>\n",
       "      <td>9609</td>\n",
       "      <td>73.8</td>\n",
       "      <td>43.1</td>\n",
       "      <td>22.3</td>\n",
       "      <td>15.0</td>\n",
       "      <td>6.9</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>men</th>\n",
       "      <td>10391</td>\n",
       "      <td>73.9</td>\n",
       "      <td>46.3</td>\n",
       "      <td>24.0</td>\n",
       "      <td>15.9</td>\n",
       "      <td>7.9</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>rural</th>\n",
       "      <td>8426</td>\n",
       "      <td>68.3</td>\n",
       "      <td>41.8</td>\n",
       "      <td>19.3</td>\n",
       "      <td>12.0</td>\n",
       "      <td>5.6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>urban</th>\n",
       "      <td>11574</td>\n",
       "      <td>78.0</td>\n",
       "      <td>46.9</td>\n",
       "      <td>26.1</td>\n",
       "      <td>18.0</td>\n",
       "      <td>8.7</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "             n  aware  intend  initiate  complete  repeat\n",
       "segment                                                  \n",
       "all      20000   73.9    44.8      23.2      15.5     7.4\n",
       "women     9609   73.8    43.1      22.3      15.0     6.9\n",
       "men      10391   73.9    46.3      24.0      15.9     7.9\n",
       "rural     8426   68.3    41.8      19.3      12.0     5.6\n",
       "urban    11574   78.0    46.9      26.1      18.0     8.7"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "seg_rows = []\n",
    "for name, mask in [(\"all\", None), (\"women\", users.sex == \"F\"), (\"men\", users.sex == \"M\"),\n",
    "                   (\"rural\", users.area == \"rural\"), (\"urban\", users.area == \"urban\")]:\n",
    "    b, g = funnel(users, events, mask)\n",
    "    seg_rows.append({\"segment\": name, \"n\": b, **{s: round(v, 1) for s, v in zip(g.step, g.pct_of_base)}})\n",
    "segments = pd.DataFrame(seg_rows).set_index(\"segment\")\n",
    "segments"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "a6bdaaed",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-11-03T16:08:23.102190Z",
     "iopub.status.busy": "2026-11-03T16:08:23.101935Z",
     "iopub.status.idle": "2026-11-03T16:08:23.629041Z",
     "shell.execute_reply": "2026-11-03T16:08:23.628183Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "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Whe3RYsW5rLLLjMDBgywziuuKuBo5syZ06RKlcpkyZLF7N271y5HIHbq1MmULl06QTUzf/5806BBA7sP6XnP4eTJk2b9+vU2P46ff/7Zfjp37hxyHJxCBDQiOEeOHEHnlXJYu3ZtSBrRWLlypS0bxDEi3sF3xNxvv/1m/z916lRIEnxnOUIeN9ht7yDU4KOPPrINB8po3759dtXMmTPtts8++6xZvXq1Xfb777+b/v37h6SPIz1w4EC7bPbs2bbx4E37mWeeMU8//bRZsGBBcDkNlzfeeCMkHRxs19g4fPiweffdd80jjzxihfmhQ4fstunTpzfNmjUzEyZMSFA9xkeyEK9cJP/880+wEBxY6QcPHgx+p3C8hQzbt283+/fvDzlPVP6aNWtClnHRsi/H2rNnj/n7779D1tPi4uYTQgghxP8gJIAwAdetX7FiRStGASGLo0lIAOI0HEQMgteB85k5c2Yr7ABX86+//rLOLSCGEyIQw0FLILwjgRBEFCNIgXhP3M/333/fZMiQIWQX8tmqVStTv359M2jQIHP77bebnTt32jJAOLL+dCCiCUXAjSY8oG3btlbcASES5OHSSy+1/4enhU5BcLZu3dqKv2zZslmnd9KkSXZ/yuuFF16wwrhIkSJW+JMnHG7qge9VqlSx2xUqVMiKUXSR4/XXX7c6CEaPHh3US99995258cYbTcaMGW0dcUycWUAjjRgxIuSU33vvPfPff//ZZZQV25YvX958+eWXIeEeLCMvZ5PUZzOxxPDaa6+ZV155xbY0aD00bdrUfP7559bWp1WH7f/mm2/apClwLj5aFMWLF7eClFYZN07z5s3NuHHjrOqn5cZFSbzO999/by655BKzadMma83369fPPP/887Zlxg1CIDHdH6znIqtWrZptNRQoUCDi6ZCuN8DZtXiEEEKICxGEEm5leDc57itOH2IJFzESCCAcOsQf7+AhQ4bYrnIX9+r2xc1E/DqBSExofAIxHAY+8S6PJKLnzp1rBSXCytGnTx/7zkegRurWxmlEDOfOndsKSM4BIYggjI/nnnvOlpmLr61bt66pV6+e6dChg7nvvvvMtGnTbBww/0cDXdOlSxe7GhGLWHUiHzOP2N506dJZ/dSzZ08zduxYc91119nticdFXw0fPtzug65hG0QrIhg9FQ7rKZMHHnjAriLe97HHHrPO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bmzFjJd33nnHlC9f3txzzz0hQmrbtm2mVatW5tixYzGXwoEDB8xrr71m8wS7d+82devWDfn06NEjmN7OnTtN586dzdVXX233mTFjRsixPvnkE1OxYkXTsmVLc/jw4eC6/fv3m9tvv93s27cv5ryFM2XKFJM/f35Tq1Yts3Xr1kSncyYgmgsVKmS++uqrM0nmtPz222/m3nvvPWfpCyFEcuK8i9eFCxfal9jq1atjKofu3bubjh07Rt22TZs25rnnnospLSGSE6+88or5+OOP7fXbrVs307dvXzNixAibxaNHj1oxmCNHDjNkyBAr+ho1amQFbTiIo5tuusn+RQAjhuvXrx8Ua4cOHbLiddasWWbv3r1m5syZwSTuv/9+07x5c5M2bdqYi2bixImmQIECpkqVKnafdevWmaVLl5pnn302+LnrrruC6d15551WXA8aNMjccsst5uabbzYrV66068nzCy+8YKZNm2Zy5cplvv322+B+3PvXXXedyZo1a8x5C2fYsGGmQ4cO9viI2KQgZcqUZvjw4aZevXrn7PB33HGH+fXXX82KFSvO2TGEECK5cN7Fa+7cuc21115rX8qxUK5cOVOpUiW7Ke5QsWLFzF9//RXclRcozlQsfP/996ZGjRqxbCrEOefPP/80L774orn11lut69ipU6egeMOtxEkbMGCAvWYRcqVKlTJz5syJky+EGQLp3XfftfcWIrJw4cJBkYpgzZAhg8mcObMpWLCg+ffff20aCLvs2bObFi1aJOhc586da4W0Y/369aZ48eJWMLtPhQoV7GqEM44nwrV27dqmS5cuNo84ou6ePnLkiMmZM6d1J13evvvuO5sujm18IOjffPNN069fP7NkyRK7+fHjx02fPn3s92XLltmGQjg0ENhmz549pn///nZ/J6qBhvb48ePNL7/8Ynr27Bl0p+fPn2/DJjjmf//9Z7ddsGCBGTlyZMghcENHjRpll9FY9zrILk9vvPGG+eeff4L7/f3338EGjAOXG3fblRfH6dWrl/nhhx/MiRMn7HKep9TJN998E19xCSGE7znv4hXHhhcJLyugC5IXDWzfvt2+ULzQbdi2bVvr0PAAx+XhxX7w4EG7Ga4K3aReiC/buHFjSBck6fKi2bBhg32Zhx9n165dZ9Q9KURC+fzzz02zZs2Cu+GaIeAAl/D5558Prlu8eLFd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2GOPmYcfftgUK1YsaTIgkpwFCxaYpk2bmooVK5o5c+YE8+PECNeH44orroiY3++++87ceuutVqA6smTJYv9dt26dmTx5svnxxx9N3bp1zX333Wfy589vjh8/bu655x7z1ltvRUwzGl988YW5/vrrTd68ee0mf/75pz02Arpt27bm1VdftemOGTPGVKlSxWTNmjWYFMdkGyeYEaelS5c2r7zyimndurVp0KCB3XblypXmzTffNHPnzk1Q3ryQrx9++MFs2bIlWBZJQePGjaPW29kgbdq0ttHz3nvv2fIWQgiRvPG9eH377bdNs2bNYhKvvIj79u2rLsILDETWRx99ZEXeLbfcEjy79evXW0fy5ptvjveM2RYBfPXVV8fZdsOGDaZQoUImW7ZsJl++fGbTpk1WvOLCIharV68eb/peEJS4pw5EJm7rgw8+aBeVK1fODBgwwDqfJUqUsB8HbirfGzZsaBeRtzJlypiiRYuazZs322XshwuNGMucOfNp8xYIBKxwpwxLlSplyyBVqlRWqI8fP966kkOGDLGincaBl2nTptkyP3TokJk1a5a56qqrzG233RbcBMe0SZMmZsKECeayyy4zN9xwg9123LhxZuPGjaZmzZqmdu3adnvuY1zeAgUKBPd3y+jWJ3TBwfl99dVX5p9//jHly5c3N910U0j5UCcFCxa0y3799Vezb98+e2z466+/bH4uvfRSWwd58uSxy9u0aWMbEEIIIZI/iQobwP3ZtWtX1LM7evRosNvTC/vx4gG6ZHlxOnjB7NixI2T7kydP2n2AmLvDhw/HVKKku3PnzjhpsYwXHvkjbS900x45ciSm9EXyApfSOY5eEHbHjh0zvXv3ts4k3fWRQFBx7SFsnnrqKfPBBx+EXGvXXHONXXfvvfda0YU7Rzf/999/n6judK7BkiVLBrPiwhuIgcV9Xb16tXnjjTdM6tShbUvuHQQz26RIkcLu37JlS/Paa6+Z22+/3X6ABtp1111nxWF84DhSPtxbCGZE3qlTp+yxKDvuJe4Ld996QYTS80GeuKeefvppW0aO5557znbHz5w5095v3GOERSAeua/ZlnoBYk6HDRsW3HfevHn2PHPlymWddcIsgHzUq1fPDB482OaZ+kJ4OigLys+BCMfBBlx5GhrU9R9//GFddsJNAGGOQN66dWt8RSaEECKJSZB43bt3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iUCuXLkC/fr1s0f/8MMPA3Xq1AmcOnUqptwMHjw4kDNnzsC4ceMCq1atCvTu3TuQPn36wOrVqwMHDx4MrFu3LlCkSJHAgAED7P8nTpyIk+62bdsCWbNmDfTt2zewfv36wKRJkwI5cuQIjBo1ym47bdq0QObMmYP75c2bN/D111/b71OmTAmkS5cuMGTIEHvMd999N5A7d+5A2bJl7fojR46gSgN//PGH/d6iRQt7rOeee87md+zYsfZY7A9Lly612x84cMB+f+mllwKlSpUKzJw5M7B27dpAx44dA8WKFQuu93L48OFApkyZAlOnTrWLZ82aZcumTJkywc0aN24cePTRR+13l1fOZc2aNYFu3boFsmfPHiyjNm3aBB5++GG77eTJk+06B/moWrWqrUPOo1mzZoEqVarYff/99197nnfddZct8+PHj8cp8xEjRtgyfeSRR+z+w4cPt/VGfQLpXH311Ta/ixcvDvz66682/aZNmwbTooyHDh1qv5OP1KlT23qmHkgvT548gYIFCwa3Jz+1atUKLFq0KLBy5cpAo0aNAtddd13wWitatGigePHi9lqiHoCy4jh//vmn3YftX3755TjnI4Q4/0i8CiGSHARU/vz5reCJFYTpoEGDQjZHlHTp0iW4DIE8evToqEm+8MILdh8v3bt3D1xzzTV20enEK/t17tw5ZF9E3+nEa7Vq1UK2f+2114Lbe8XryZMnrdD98ccfg9vv27fPCtSvvvoq4vkg7nr06GHXPf/884GePXtacbxhw4bAsWPHAlmyZLHn49i/f3/w/xUrVljh7IRbNPG6Y8eOQKpUqayYc1BnKVKkCMyfP98uat++faBTp05Ryxzxmi1btpDGBHlv27at3WfChAk2r5yv459//rHHcMf1itd27doFWrZsGXI86sWJ140bNwZSpkwZ2LRpU3CbZcuW2fNdvny5XYZ4HThwYEgat912m/04AU4ZCiGSBwobEEIkKXSP0z3LABviXunyb9iwoXnwwQfN3r17I+aNLl3iZK+99tqQ9XTZn24Uejh06fOpW7du8DNlyhQb0hAfzGRQrVq1kM0qV6582t3CB43VqFHDjoynDLzQDb9v3z47UMrlrXHjxiZVqlRR88b6yZMn22SItW3QoIG57rrrzNSpU82cOXNMypQpTe3ate16whfYhu54zoGQC6BcTwfnTF4feOCBYL7at29vQw9iKTNH3rx57bk4SpcubQe3AbMREM5AV72D0Il8+fJFrNtI9eAtZ9Lj3Nu0aRPMM+dNXKs3z+TJC6ERv/zyiw2/uOeee8zEiRNPWzZCiPPHmY+IEEKIM4Aps4hDRCAQA4sYQsASo8mHGNhw0qRJYwVJ+LRSxGMmZLAQoot4R4SylxQpUsR7RsStOsHliE/8uZkHHMRiunPxQr6AfBE76oVY2UjcfPPNNnaU2QEQbAh7hB1Te61evdo2CDgWPProo3ZWBwTaXXfdZUqVKhXnOJEgX5QN+4UPaoo1ThlOV77p0qWLOF1YtLqlvsNngPB+J8/ktWfPnnGOe9VVV0U8T6D8aEQg8pk2rF27dvbadFOnCSGSDjmvQogkA5HFtEoffvihzQMiq3jx4nYWAgYCRZtTFYGD8PC6YQx84ntCpsTCKV27dq11KRkQxSdXrlwxCblrrrnGDjpyAhpxNWbMmNOW5bRp06zr6WA+1fLly8fZB5cxf/78dluXL/LIoCVmMYgEIpcBR0xDhQONqGvUqJF1XWfOnGmdWQdubLdu3Uz37t3teUQbzBYOApVBUaTt8oW7e+jQIVtuDgaEJRbq5I8//jCbN28OJjFv3jw7sC9SWbHMO4gOvLM8cJ3gFjPwyuUZYcrgq5w5c0bNJmlu2bLFNGnSxA7iY3q30011JoQ4f8h5FUIkCYi+tm3bmoEDB9r5XoGwAWYIYAYAuu8RstF45ZVXTNOmTa1oRaB8/vnnVmwgyGKlY8eOdsYCBAqhC5s2bTK9e/e23coVKlQ4bTKM1kf4Ibbo/kckMgKfHzaIRsaMGW2eOdbChQvt5P/RBBEilHwwKp5R+WPHjrVil7AInOpIIFAJNWD6MaD86J7//fffrZB1ECrAjACMvkfY4XDH6jZz3q1bt7bHQUgzwwL15WZCIATg/ffft6P3mzVrZkVjQiCEgbziFPMjFohM6oR6Jb/h4Mwz0wDXEmXLj1EQiuFAVDPrAo0hpk0jPzSWaLQgZqNBmZAO++Ko86MH5EkIkfRIvAohkgTcQEQjosKB20gYwb333mtjDRGW0UBI4GSyDYIFsYkg9Ao7utIRxNFATP7222+mX79+VkjSxYwo7tChg90FUe3N32233RYUULijixcvtqIS0fzee+9ZEefyTFjDnXfeGcwPbh/f+SUtup5xSnH36tevb4/FFE2sd93xdOdz/I8++sh88803VhTOnTvXFC5cOOr5kNdFixaZW2+9NbgN4o75br0iEicREco5I/zIe58+fezUVICDS9kAsaCIUAchA4hi11hgmi2EnZvujJCE3bt327AEhH24eCXs4aabbgo5B2Jcvc4tZcp18PHHH1uX/aWXXrLXhIO6dw0byoMfLKAO2Ye4XoTzyJEjg9sjfik/8kRjoFKlSjZtXGSgvMLLlf0pE4Q4TnPnzp3tdFtCiKQnBePGkj4bQgjhLxhQxY8teB1NYlQRsohNIYQQ5wY5r0IIkQjovmcifSavJxZ01qxZ1kmla18IIcS5Q86rEEIkklWrVtnYXAYYEQbAdEz8CpcQQohzh8SrEEIIIYTwDZoqSwghhBBC+AaJVyGEEEII4RskXoUQQgghhG+QeBVCCCGEEL5B4lUIIYQQQvgGiVchhBBCCOEbJF6FEEIIIYRvkHgVQgghhBC+QeJVCCGEEEL4hv8Hge5HXDpTtPkAAAAASUVORK5CYII=",
      "text/plain": [
       "<Figure size 700x320 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "fig, ax = plt.subplots(figsize=(7, 3.2))\n",
    "ax.barh(f.step[::-1], f.pct_of_base[::-1], color=[\"#1f5f63\", \"#a3471c\", \"#1f5f63\", \"#1f5f63\", \"#1f5f63\"])\n",
    "for y, (v, c) in enumerate(zip(f.pct_of_base[::-1], f.conversion_from_previous[::-1])):\n",
    "    ax.text(v + 1, y, f\"{v:.1f}%  ({c:.0f}% of previous)\", va=\"center\", fontsize=9)\n",
    "ax.set_xlim(0, 100); ax.set_xlabel(\"% of eligible wallet holders\"); ax.set_title(\"Journey funnel (synthetic)\")\n",
    "ax.spines[[\"top\", \"right\"]].set_visible(False); plt.tight_layout(); plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fea52d4e",
   "metadata": {},
   "source": [
    "Reading: the target behaviour (a deposit in month 1) is reached by 15.5 % of holders, and 7.4 % deposit in both months. The largest absolute loss is between *aware* and *intend*; but more than half of those who intend never open the deposit flow, which is an intention–behaviour gap that information alone does not close."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c4dd9d5f",
   "metadata": {},
   "source": [
    "## 3. Barrier register and ranking\n",
    "\n",
    "Scales (full definitions in `scoring-rubric-en.md`): **P** prevalence (share affected: 1 = under 10 %, 5 = 60 % or more), **S** severity (1 = minor irritation, 5 = makes the deposit impossible), **T** tractability (1 = outside the programme's control, 5 = cheap, quick and testable in a trial). Ties are broken by severity, then prevalence, then id."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "3e59fffa",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-11-03T16:08:23.631658Z",
     "iopub.status.busy": "2026-11-03T16:08:23.631040Z",
     "iopub.status.idle": "2026-11-03T16:08:23.647391Z",
     "shell.execute_reply": "2026-11-03T16:08:23.646318Z"
    }
   },
   "outputs": [],
   "source": [
    "# Barrier register. P = prevalence, S = severity, T = tractability, each 1-5 (rubric in scoring-rubric.md).\n",
    "COMB = {\n",
    "    \"C-Ps\": (\"Capability, psychological\", \"Capacité psychologique\"),\n",
    "    \"C-Ph\": (\"Capability, physical\", \"Capacité physique\"),\n",
    "    \"O-Ph\": (\"Opportunity, physical\", \"Opportunité physique\"),\n",
    "    \"O-So\": (\"Opportunity, social\", \"Opportunité sociale\"),\n",
    "    \"M-Re\": (\"Motivation, reflective\", \"Motivation réfléchie\"),\n",
    "    \"M-Au\": (\"Motivation, automatic\", \"Motivation automatique\"),\n",
    "}\n",
    "STEP_LABEL = {\n",
    "    \"aware\": (\"Aware\", \"Connaître\"), \"intend\": (\"Intend\", \"Avoir l’intention\"), \"initiate\": (\"Initiate\", \"Amorcer\"),\n",
    "    \"complete\": (\"Complete\", \"Finaliser\"), \"repeat\": (\"Repeat\", \"Recommencer\"),\n",
    "}\n",
    "SOURCE_LABEL = {\n",
    "    \"admin\": (\"administrative data\", \"données administratives\"), \"survey\": (\"short survey\", \"court sondage\"),\n",
    "    \"testing\": (\"user testing\", \"tests utilisateurs\"), \"interviews\": (\"interviews\", \"entretiens\"),\n",
    "}\n",
    "PACKAGES = {\n",
    "    \"P1\": (\"Simplify the savings path\", \"Simplifier le parcours d’épargne\"),\n",
    "    \"P2\": (\"Prompt when money arrives\", \"Rappeler quand l’argent arrive\"),\n",
    "    \"P3\": (\"Opt-in automatic set-aside\", \"Mise de côté automatique, sur adhésion\"),\n",
    "    \"P4\": (\"Explain and reassure at the point of use\", \"Informer et rassurer au moment de l’usage\"),\n",
    "    \"P5\": (\"Show that others save\", \"Montrer que d’autres épargnent\"),\n",
    "    \"S\": (\"Structural: outside a behavioural package\", \"Structurel : hors d’un dispositif comportemental\"),\n",
    "}\n",
    "\n",
    "BARRIERS = [\n",
    "    # id, step, COM-B, sources, P, S, T, package, EN label, FR label, EN test, FR test\n",
    "    (\"B01\", \"aware\", \"C-Ps\", [\"admin\", \"survey\"], 3, 5, 5, \"P4\",\n",
    "     \"Does not know the wallet has a savings feature, or what it does\",\n",
    "     \"Ignore que le portefeuille offre une fonction d’épargne, ou à quoi elle sert\",\n",
    "     \"Share of holders who never opened the savings menu in 12 months (logs); unprompted-recall item in the survey\",\n",
    "     \"Part des titulaires n’ayant jamais ouvert le menu épargne en 12 mois (journaux) ; question de rappel spontané dans le sondage\"),\n",
    "    (\"B02\", \"intend\", \"M-Re\", [\"survey\", \"interviews\"], 3, 3, 4, \"P4\",\n",
    "     \"Sees saving as something for larger amounts, not for people like them\",\n",
    "     \"Pense que l’épargne est réservée aux gros montants, pas aux gens comme soi\",\n",
    "     \"Agreement items on the smallest amount worth saving; probing in interviews\",\n",
    "     \"Énoncés d’accord sur le plus petit montant « qui vaut la peine » ; relances en entretien\"),\n",
    "    (\"B03\", \"intend\", \"M-Re\", [\"interviews\", \"survey\"], 4, 4, 3, \"P4\",\n",
    "     \"Fears that money in the savings pocket cannot be taken out quickly in an emergency\",\n",
    "     \"Craint de ne pas pouvoir retirer vite l’argent épargné en cas d’urgence\",\n",
    "     \"Stated belief compared with the actual withdrawal rule; accounts of past experiences in interviews\",\n",
    "     \"Croyance déclarée comparée à la règle de retrait réelle ; récits d’expériences passées en entretien\"),\n",
    "    (\"B04\", \"initiate\", \"M-Au\", [\"admin\", \"survey\"], 5, 3, 4, \"P3\",\n",
    "     \"Intends to save but spends first when money arrives\",\n",
    "     \"Compte épargner mais dépense d’abord quand l’argent arrive\",\n",
    "     \"Time from an inflow to the first payment vs. to a savings deposit (logs); stated plan vs. logged behaviour\",\n",
    "     \"Délai entre une entrée d’argent et le premier paiement, comparé au délai jusqu’au dépôt (journaux) ; intention déclarée comparée au comportement observé\"),\n",
    "    (\"B05\", \"initiate\", \"C-Ps\", [\"admin\", \"interviews\"], 4, 3, 5, \"P2\",\n",
    "     \"Forgets: nothing prompts a deposit when money is in the wallet\",\n",
    "     \"Oublie : rien ne rappelle le dépôt au moment où l’argent est sur le portefeuille\",\n",
    "     \"Share of months with an inflow above the usual deposit but no savings deposit (logs)\",\n",
    "     \"Part des mois avec une entrée d’argent supérieure au dépôt habituel mais sans dépôt d’épargne (journaux)\"),\n",
    "    (\"B06\", \"initiate\", \"O-Ph\", [\"admin\", \"survey\"], 4, 4, 2, \"S\",\n",
    "     \"No balance in the wallet; cashing in means a trip to an agent\",\n",
    "     \"Pas de solde sur le portefeuille ; l’alimenter exige un déplacement chez un agent\",\n",
    "     \"Share of months with no inflow (logs); distance to the nearest active agent (agent register)\",\n",
    "     \"Part des mois sans entrée d’argent (journaux) ; distance à l’agent actif le plus proche (registre des agents)\"),\n",
    "    (\"B07\", \"complete\", \"O-Ph\", [\"testing\", \"admin\"], 3, 4, 5, \"P1\",\n",
    "     \"The savings path is buried: seven USSD screens and a session that times out\",\n",
    "     \"Le parcours d’épargne est enfoui : sept écrans USSD et une session qui expire\",\n",
    "     \"Timed think-aloud tests; abandonment by screen in session logs\",\n",
    "     \"Tests chronométrés avec verbalisation ; abandons par écran dans les journaux de session\"),\n",
    "    (\"B08\", \"complete\", \"M-Re\", [\"testing\", \"survey\"], 2, 4, 3, \"P1\",\n",
    "     \"Is not sure whether moving money to savings costs a fee\",\n",
    "     \"Ne sait pas si le transfert vers l’épargne est payant\",\n",
    "     \"Fee belief compared with the actual tariff; hesitation observed at the confirmation screen\",\n",
    "     \"Croyance sur les frais comparée au barème réel ; hésitation observée à l’écran de confirmation\"),\n",
    "    (\"B09\", \"complete\", \"C-Ps\", [\"testing\", \"survey\"], 2, 4, 4, \"P1\",\n",
    "     \"Has difficulty reading menu text or checking amounts on screen\",\n",
    "     \"Lit difficilement les menus ou vérifie mal les montants à l’écran\",\n",
    "     \"Task success in user tests by literacy level; short reading item in the survey\",\n",
    "     \"Réussite des tâches en test selon le niveau de lecture ; court exercice de lecture dans le sondage\"),\n",
    "    (\"B10\", \"repeat\", \"O-So\", [\"interviews\", \"survey\"], 2, 3, 2, \"S\",\n",
    "     \"Visible savings attract requests from relatives\",\n",
    "     \"Une épargne visible attire les demandes des proches\",\n",
    "     \"Accounts in interviews; list-experiment item to limit social-desirability bias\",\n",
    "     \"Récits en entretien ; question en liste (list experiment) pour limiter le biais de désirabilité sociale\"),\n",
    "    (\"B11\", \"repeat\", \"O-Ph\", [\"admin\", \"survey\"], 4, 4, 1, \"S\",\n",
    "     \"Income is too irregular or too low to set money aside every month\",\n",
    "     \"Revenu trop irrégulier ou trop faible pour mettre de côté chaque mois\",\n",
    "     \"Coefficient of variation of monthly inflows (logs); income module of the survey\",\n",
    "     \"Coefficient de variation des entrées mensuelles (journaux) ; module revenu du sondage\"),\n",
    "    (\"B12\", \"repeat\", \"M-Au\", [\"testing\", \"admin\"], 3, 2, 5, \"P2\",\n",
    "     \"No feedback: the savings balance and progress are not shown after a deposit\",\n",
    "     \"Aucune rétroaction : ni le solde épargné ni la progression ne s’affichent après un dépôt\",\n",
    "     \"Review of confirmation messages; repeat rate after a first deposit (logs)\",\n",
    "     \"Examen des messages de confirmation ; taux de récidive après un premier dépôt (journaux)\"),\n",
    "    (\"B13\", \"intend\", \"O-So\", [\"survey\", \"interviews\"], 3, 2, 4, \"P5\",\n",
    "     \"Does not see peers using the savings feature\",\n",
    "     \"Ne voit pas ses pairs utiliser la fonction d’épargne\",\n",
    "     \"Perceived share of peers who save in the wallet vs. actual share (logs)\",\n",
    "     \"Part perçue des pairs qui épargnent sur le portefeuille comparée à la part réelle (journaux)\"),\n",
    "    (\"B14\", \"initiate\", \"O-Ph\", [\"admin\"], 1, 5, 3, \"P1\",\n",
    "     \"The account tier (identity-verification level) does not include the savings feature\",\n",
    "     \"Le niveau de compte (vérification d’identité) ne donne pas accès à l’épargne\",\n",
    "     \"Share of active holders on the entry tier (identity-verification register)\",\n",
    "     \"Part des titulaires actifs au niveau d’entrée (registre de vérification d’identité)\"),\n",
    "]\n",
    "DEFAULT_WEIGHTS = {\"P\": 1.0, \"S\": 1.0, \"T\": 1.0}\n",
    "DEFAULT_TOP_K = 5\n",
    "\n",
    "\n",
    "def score(p, s, t, w=DEFAULT_WEIGHTS):\n",
    "    return (p ** w[\"P\"]) * (s ** w[\"S\"]) * (t ** w[\"T\"])\n",
    "\n",
    "\n",
    "def rank_barriers(w=DEFAULT_WEIGHTS, overrides=None):\n",
    "    \"\"\"Score descending; ties broken by severity, then prevalence (both descending), then id.\"\"\"\n",
    "    rows = []\n",
    "    for b in BARRIERS:\n",
    "        bid, step, comb, src, p, s, t, pkg = b[:8]\n",
    "        if overrides and bid in overrides:\n",
    "            p, s, t = overrides[bid]\n",
    "        rows.append({\"id\": bid, \"step\": step, \"com_b\": comb, \"P\": p, \"S\": s, \"T\": t, \"package\": pkg,\n",
    "                     \"score\": score(p, s, t, w), \"barrier\": b[8]})\n",
    "    rows.sort(key=lambda r: (-round(r[\"score\"], 9), -r[\"S\"], -r[\"P\"], r[\"id\"]))\n",
    "    for i, r in enumerate(rows):\n",
    "        r[\"rank\"] = i + 1\n",
    "    return pd.DataFrame(rows)\n",
    "\n",
    "\n",
    "def top_k_summary(ranked, k=DEFAULT_TOP_K):\n",
    "    top = ranked.head(k)\n",
    "    by_comb = top.groupby(\"com_b\")[\"score\"].agg([\"count\", \"sum\"]).sort_values(\"sum\", ascending=False)\n",
    "    by_pkg = top.groupby(\"package\")[\"score\"].agg([\"count\", \"sum\"])\n",
    "    by_pkg[\"share_%\"] = 100 * by_pkg[\"sum\"] / by_pkg[\"sum\"].sum()\n",
    "    return by_comb, by_pkg.sort_values([\"sum\", \"count\"], ascending=False)\n",
    "\n",
    "\n",
    "def barrier_register(lang=\"en\"):\n",
    "    j = 0 if lang == \"en\" else 1\n",
    "    ranked = rank_barriers().set_index(\"id\")\n",
    "    cols_en = [\"id\", \"barrier\", \"journey_step\", \"com_b_component\", \"evidence_sources\", \"how_to_test\",\n",
    "               \"prevalence_1_5\", \"severity_1_5\", \"tractability_1_5\", \"score_PxSxT\", \"rank\", \"intervention_package\"]\n",
    "    cols_fr = [\"id\", \"frein\", \"etape_du_parcours\", \"composante_com_b\", \"sources_de_donnees\", \"comment_le_verifier\",\n",
    "               \"prevalence_1_5\", \"gravite_1_5\", \"modifiabilite_1_5\", \"score_PxGxM\", \"rang\", \"dispositif_d_intervention\"]\n",
    "    rows = []\n",
    "    for b in BARRIERS:\n",
    "        bid, step, comb, src, p, s, t, pkg = b[:8]\n",
    "        rows.append([bid, b[8 + j], STEP_LABEL[step][j], f\"{comb} ({COMB[comb][j]})\",\n",
    "                     \"; \".join(SOURCE_LABEL[x][j] for x in src), b[10 + j], p, s, t,\n",
    "                     int(ranked.loc[bid, \"score\"]), int(ranked.loc[bid, \"rank\"]), f\"{pkg}: {PACKAGES[pkg][j]}\"])\n",
    "    df = pd.DataFrame(rows, columns=cols_en if lang == \"en\" else cols_fr)\n",
    "    return df.sort_values(df.columns[10]).reset_index(drop=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "b69366c0",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-11-03T16:08:23.649063Z",
     "iopub.status.busy": "2026-11-03T16:08:23.648887Z",
     "iopub.status.idle": "2026-11-03T16:08:23.662719Z",
     "shell.execute_reply": "2026-11-03T16:08:23.661629Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>rank</th>\n",
       "      <th>id</th>\n",
       "      <th>step</th>\n",
       "      <th>com_b</th>\n",
       "      <th>P</th>\n",
       "      <th>S</th>\n",
       "      <th>T</th>\n",
       "      <th>score</th>\n",
       "      <th>package</th>\n",
       "      <th>barrier</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1</td>\n",
       "      <td>B01</td>\n",
       "      <td>aware</td>\n",
       "      <td>C-Ps</td>\n",
       "      <td>3</td>\n",
       "      <td>5</td>\n",
       "      <td>5</td>\n",
       "      <td>75.0</td>\n",
       "      <td>P4</td>\n",
       "      <td>Does not know the wallet has a savings feature...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2</td>\n",
       "      <td>B07</td>\n",
       "      <td>complete</td>\n",
       "      <td>O-Ph</td>\n",
       "      <td>3</td>\n",
       "      <td>4</td>\n",
       "      <td>5</td>\n",
       "      <td>60.0</td>\n",
       "      <td>P1</td>\n",
       "      <td>The savings path is buried: seven USSD screens...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>3</td>\n",
       "      <td>B04</td>\n",
       "      <td>initiate</td>\n",
       "      <td>M-Au</td>\n",
       "      <td>5</td>\n",
       "      <td>3</td>\n",
       "      <td>4</td>\n",
       "      <td>60.0</td>\n",
       "      <td>P3</td>\n",
       "      <td>Intends to save but spends first when money ar...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>4</td>\n",
       "      <td>B05</td>\n",
       "      <td>initiate</td>\n",
       "      <td>C-Ps</td>\n",
       "      <td>4</td>\n",
       "      <td>3</td>\n",
       "      <td>5</td>\n",
       "      <td>60.0</td>\n",
       "      <td>P2</td>\n",
       "      <td>Forgets: nothing prompts a deposit when money ...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>5</td>\n",
       "      <td>B03</td>\n",
       "      <td>intend</td>\n",
       "      <td>M-Re</td>\n",
       "      <td>4</td>\n",
       "      <td>4</td>\n",
       "      <td>3</td>\n",
       "      <td>48.0</td>\n",
       "      <td>P4</td>\n",
       "      <td>Fears that money in the savings pocket cannot ...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>6</td>\n",
       "      <td>B02</td>\n",
       "      <td>intend</td>\n",
       "      <td>M-Re</td>\n",
       "      <td>3</td>\n",
       "      <td>3</td>\n",
       "      <td>4</td>\n",
       "      <td>36.0</td>\n",
       "      <td>P4</td>\n",
       "      <td>Sees saving as something for larger amounts, n...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>7</td>\n",
       "      <td>B06</td>\n",
       "      <td>initiate</td>\n",
       "      <td>O-Ph</td>\n",
       "      <td>4</td>\n",
       "      <td>4</td>\n",
       "      <td>2</td>\n",
       "      <td>32.0</td>\n",
       "      <td>S</td>\n",
       "      <td>No balance in the wallet; cashing in means a t...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>8</td>\n",
       "      <td>B09</td>\n",
       "      <td>complete</td>\n",
       "      <td>C-Ps</td>\n",
       "      <td>2</td>\n",
       "      <td>4</td>\n",
       "      <td>4</td>\n",
       "      <td>32.0</td>\n",
       "      <td>P1</td>\n",
       "      <td>Has difficulty reading menu text or checking a...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>9</td>\n",
       "      <td>B12</td>\n",
       "      <td>repeat</td>\n",
       "      <td>M-Au</td>\n",
       "      <td>3</td>\n",
       "      <td>2</td>\n",
       "      <td>5</td>\n",
       "      <td>30.0</td>\n",
       "      <td>P2</td>\n",
       "      <td>No feedback: the savings balance and progress ...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>10</td>\n",
       "      <td>B08</td>\n",
       "      <td>complete</td>\n",
       "      <td>M-Re</td>\n",
       "      <td>2</td>\n",
       "      <td>4</td>\n",
       "      <td>3</td>\n",
       "      <td>24.0</td>\n",
       "      <td>P1</td>\n",
       "      <td>Is not sure whether moving money to savings co...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10</th>\n",
       "      <td>11</td>\n",
       "      <td>B13</td>\n",
       "      <td>intend</td>\n",
       "      <td>O-So</td>\n",
       "      <td>3</td>\n",
       "      <td>2</td>\n",
       "      <td>4</td>\n",
       "      <td>24.0</td>\n",
       "      <td>P5</td>\n",
       "      <td>Does not see peers using the savings feature</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>11</th>\n",
       "      <td>12</td>\n",
       "      <td>B11</td>\n",
       "      <td>repeat</td>\n",
       "      <td>O-Ph</td>\n",
       "      <td>4</td>\n",
       "      <td>4</td>\n",
       "      <td>1</td>\n",
       "      <td>16.0</td>\n",
       "      <td>S</td>\n",
       "      <td>Income is too irregular or too low to set mone...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>12</th>\n",
       "      <td>13</td>\n",
       "      <td>B14</td>\n",
       "      <td>initiate</td>\n",
       "      <td>O-Ph</td>\n",
       "      <td>1</td>\n",
       "      <td>5</td>\n",
       "      <td>3</td>\n",
       "      <td>15.0</td>\n",
       "      <td>P1</td>\n",
       "      <td>The account tier (identity-verification level)...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>13</th>\n",
       "      <td>14</td>\n",
       "      <td>B10</td>\n",
       "      <td>repeat</td>\n",
       "      <td>O-So</td>\n",
       "      <td>2</td>\n",
       "      <td>3</td>\n",
       "      <td>2</td>\n",
       "      <td>12.0</td>\n",
       "      <td>S</td>\n",
       "      <td>Visible savings attract requests from relatives</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "    rank   id      step com_b  P  S  T  score package  \\\n",
       "0      1  B01     aware  C-Ps  3  5  5   75.0      P4   \n",
       "1      2  B07  complete  O-Ph  3  4  5   60.0      P1   \n",
       "2      3  B04  initiate  M-Au  5  3  4   60.0      P3   \n",
       "3      4  B05  initiate  C-Ps  4  3  5   60.0      P2   \n",
       "4      5  B03    intend  M-Re  4  4  3   48.0      P4   \n",
       "5      6  B02    intend  M-Re  3  3  4   36.0      P4   \n",
       "6      7  B06  initiate  O-Ph  4  4  2   32.0       S   \n",
       "7      8  B09  complete  C-Ps  2  4  4   32.0      P1   \n",
       "8      9  B12    repeat  M-Au  3  2  5   30.0      P2   \n",
       "9     10  B08  complete  M-Re  2  4  3   24.0      P1   \n",
       "10    11  B13    intend  O-So  3  2  4   24.0      P5   \n",
       "11    12  B11    repeat  O-Ph  4  4  1   16.0       S   \n",
       "12    13  B14  initiate  O-Ph  1  5  3   15.0      P1   \n",
       "13    14  B10    repeat  O-So  2  3  2   12.0       S   \n",
       "\n",
       "                                              barrier  \n",
       "0   Does not know the wallet has a savings feature...  \n",
       "1   The savings path is buried: seven USSD screens...  \n",
       "2   Intends to save but spends first when money ar...  \n",
       "3   Forgets: nothing prompts a deposit when money ...  \n",
       "4   Fears that money in the savings pocket cannot ...  \n",
       "5   Sees saving as something for larger amounts, n...  \n",
       "6   No balance in the wallet; cashing in means a t...  \n",
       "7   Has difficulty reading menu text or checking a...  \n",
       "8   No feedback: the savings balance and progress ...  \n",
       "9   Is not sure whether moving money to savings co...  \n",
       "10       Does not see peers using the savings feature  \n",
       "11  Income is too irregular or too low to set mone...  \n",
       "12  The account tier (identity-verification level)...  \n",
       "13    Visible savings attract requests from relatives  "
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ranked = rank_barriers()\n",
    "ranked[[\"rank\", \"id\", \"step\", \"com_b\", \"P\", \"S\", \"T\", \"score\", \"package\", \"barrier\"]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "05e8213e",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-11-03T16:08:23.664385Z",
     "iopub.status.busy": "2026-11-03T16:08:23.664197Z",
     "iopub.status.idle": "2026-11-03T16:08:23.682370Z",
     "shell.execute_reply": "2026-11-03T16:08:23.681625Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "COM-B profile of the top 5:\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>count</th>\n",
       "      <th>sum</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>com_b</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>C-Ps</th>\n",
       "      <td>2</td>\n",
       "      <td>135.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>M-Au</th>\n",
       "      <td>1</td>\n",
       "      <td>60.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>O-Ph</th>\n",
       "      <td>1</td>\n",
       "      <td>60.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>M-Re</th>\n",
       "      <td>1</td>\n",
       "      <td>48.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "       count    sum\n",
       "com_b              \n",
       "C-Ps       2  135.0\n",
       "M-Au       1   60.0\n",
       "O-Ph       1   60.0\n",
       "M-Re       1   48.0"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Intervention packages the top 5 point to:\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>count</th>\n",
       "      <th>sum</th>\n",
       "      <th>share_%</th>\n",
       "      <th>label</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>package</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>P4</th>\n",
       "      <td>2</td>\n",
       "      <td>123.0</td>\n",
       "      <td>40.6</td>\n",
       "      <td>Explain and reassure at the point of use</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>P1</th>\n",
       "      <td>1</td>\n",
       "      <td>60.0</td>\n",
       "      <td>19.8</td>\n",
       "      <td>Simplify the savings path</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>P2</th>\n",
       "      <td>1</td>\n",
       "      <td>60.0</td>\n",
       "      <td>19.8</td>\n",
       "      <td>Prompt when money arrives</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>P3</th>\n",
       "      <td>1</td>\n",
       "      <td>60.0</td>\n",
       "      <td>19.8</td>\n",
       "      <td>Opt-in automatic set-aside</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "         count    sum  share_%                                     label\n",
       "package                                                                 \n",
       "P4           2  123.0     40.6  Explain and reassure at the point of use\n",
       "P1           1   60.0     19.8                 Simplify the savings path\n",
       "P2           1   60.0     19.8                 Prompt when money arrives\n",
       "P3           1   60.0     19.8                Opt-in automatic set-aside"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "by_comb, by_pkg = top_k_summary(ranked, k=DEFAULT_TOP_K)\n",
    "print(\"COM-B profile of the top 5:\"); display(by_comb)\n",
    "print(\"Intervention packages the top 5 point to:\"); display(by_pkg.assign(label=[PACKAGES[p][0] for p in by_pkg.index]).round(1))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0287eb13",
   "metadata": {},
   "source": [
    "### Sensitivity\n",
    "\n",
    "The ranking depends on the weights. Ignoring tractability ($w_T = 0$) brings the structural barriers (no cash in the wallet, irregular income) into the top 5: they are real, but no behavioural package removes them. Doubling severity ($w_S = 2$) is shown as the second check required by the rubric."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "830ee880",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-11-03T16:08:23.684549Z",
     "iopub.status.busy": "2026-11-03T16:08:23.684311Z",
     "iopub.status.idle": "2026-11-03T16:08:23.693149Z",
     "shell.execute_reply": "2026-11-03T16:08:23.692177Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "default  B01(P4) 75, B07(P1) 60, B04(P3) 60, B05(P2) 60, B03(P4) 48\n",
      "wT = 0   B03(P4) 16, B06(S) 16, B11(S) 16, B01(P4) 15, B04(P3) 15\n",
      "wS = 2   B01(P4) 375, B07(P1) 240, B03(P4) 192, B04(P3) 180, B05(P2) 180\n"
     ]
    }
   ],
   "source": [
    "for label, w in [(\"default\", DEFAULT_WEIGHTS), (\"wT = 0\", {\"P\": 1, \"S\": 1, \"T\": 0}), (\"wS = 2\", {\"P\": 1, \"S\": 2, \"T\": 1})]:\n",
    "    r = rank_barriers(w).head(5)\n",
    "    print(f\"{label:8s}\", \", \".join(f\"{i}({p}) {s:g}\" for i, p, s in zip(r.id, r.package, r.score)))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7eef0f50",
   "metadata": {},
   "source": [
    "## 4. Survey sample size\n",
    "\n",
    "Simple random sample needed to estimate a barrier's prevalence within ±3 percentage points at 95 % confidence, in the worst case $p = 0.5$: $n = z^2 p(1-p)/m^2$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "5e39349f",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-11-03T16:08:23.695033Z",
     "iopub.status.busy": "2026-11-03T16:08:23.694849Z",
     "iopub.status.idle": "2026-11-03T16:08:23.699540Z",
     "shell.execute_reply": "2026-11-03T16:08:23.698341Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1068 385\n"
     ]
    }
   ],
   "source": [
    "def survey_n(p=0.5, moe=0.03, z=1.959963984540054):\n",
    "    \"\"\"Simple-random-sample size to estimate a prevalence within +/- moe at 95 % confidence.\"\"\"\n",
    "    return math.ceil(z * z * p * (1 - p) / (moe * moe))\n",
    "\n",
    "print(survey_n(), survey_n(moe=0.05))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "002aee07",
   "metadata": {},
   "source": [
    "## 5. Barrier register (CSV) and checks against the demo defaults"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "ad45af34",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-11-03T16:08:23.701227Z",
     "iopub.status.busy": "2026-11-03T16:08:23.701062Z",
     "iopub.status.idle": "2026-11-03T16:08:23.721555Z",
     "shell.execute_reply": "2026-11-03T16:08:23.720177Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>id</th>\n",
       "      <th>barrier</th>\n",
       "      <th>journey_step</th>\n",
       "      <th>com_b_component</th>\n",
       "      <th>evidence_sources</th>\n",
       "      <th>how_to_test</th>\n",
       "      <th>prevalence_1_5</th>\n",
       "      <th>severity_1_5</th>\n",
       "      <th>tractability_1_5</th>\n",
       "      <th>score_PxSxT</th>\n",
       "      <th>rank</th>\n",
       "      <th>intervention_package</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>B01</td>\n",
       "      <td>Does not know the wallet has a savings feature...</td>\n",
       "      <td>Aware</td>\n",
       "      <td>C-Ps (Capability, psychological)</td>\n",
       "      <td>administrative data; short survey</td>\n",
       "      <td>Share of holders who never opened the savings ...</td>\n",
       "      <td>3</td>\n",
       "      <td>5</td>\n",
       "      <td>5</td>\n",
       "      <td>75</td>\n",
       "      <td>1</td>\n",
       "      <td>P4: Explain and reassure at the point of use</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>B07</td>\n",
       "      <td>The savings path is buried: seven USSD screens...</td>\n",
       "      <td>Complete</td>\n",
       "      <td>O-Ph (Opportunity, physical)</td>\n",
       "      <td>user testing; administrative data</td>\n",
       "      <td>Timed think-aloud tests; abandonment by screen...</td>\n",
       "      <td>3</td>\n",
       "      <td>4</td>\n",
       "      <td>5</td>\n",
       "      <td>60</td>\n",
       "      <td>2</td>\n",
       "      <td>P1: Simplify the savings path</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>B04</td>\n",
       "      <td>Intends to save but spends first when money ar...</td>\n",
       "      <td>Initiate</td>\n",
       "      <td>M-Au (Motivation, automatic)</td>\n",
       "      <td>administrative data; short survey</td>\n",
       "      <td>Time from an inflow to the first payment vs. t...</td>\n",
       "      <td>5</td>\n",
       "      <td>3</td>\n",
       "      <td>4</td>\n",
       "      <td>60</td>\n",
       "      <td>3</td>\n",
       "      <td>P3: Opt-in automatic set-aside</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>B05</td>\n",
       "      <td>Forgets: nothing prompts a deposit when money ...</td>\n",
       "      <td>Initiate</td>\n",
       "      <td>C-Ps (Capability, psychological)</td>\n",
       "      <td>administrative data; interviews</td>\n",
       "      <td>Share of months with an inflow above the usual...</td>\n",
       "      <td>4</td>\n",
       "      <td>3</td>\n",
       "      <td>5</td>\n",
       "      <td>60</td>\n",
       "      <td>4</td>\n",
       "      <td>P2: Prompt when money arrives</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>B03</td>\n",
       "      <td>Fears that money in the savings pocket cannot ...</td>\n",
       "      <td>Intend</td>\n",
       "      <td>M-Re (Motivation, reflective)</td>\n",
       "      <td>interviews; short survey</td>\n",
       "      <td>Stated belief compared with the actual withdra...</td>\n",
       "      <td>4</td>\n",
       "      <td>4</td>\n",
       "      <td>3</td>\n",
       "      <td>48</td>\n",
       "      <td>5</td>\n",
       "      <td>P4: Explain and reassure at the point of use</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "    id                                            barrier journey_step  \\\n",
       "0  B01  Does not know the wallet has a savings feature...        Aware   \n",
       "1  B07  The savings path is buried: seven USSD screens...     Complete   \n",
       "2  B04  Intends to save but spends first when money ar...     Initiate   \n",
       "3  B05  Forgets: nothing prompts a deposit when money ...     Initiate   \n",
       "4  B03  Fears that money in the savings pocket cannot ...       Intend   \n",
       "\n",
       "                    com_b_component                   evidence_sources  \\\n",
       "0  C-Ps (Capability, psychological)  administrative data; short survey   \n",
       "1      O-Ph (Opportunity, physical)  user testing; administrative data   \n",
       "2      M-Au (Motivation, automatic)  administrative data; short survey   \n",
       "3  C-Ps (Capability, psychological)    administrative data; interviews   \n",
       "4     M-Re (Motivation, reflective)           interviews; short survey   \n",
       "\n",
       "                                         how_to_test  prevalence_1_5  \\\n",
       "0  Share of holders who never opened the savings ...               3   \n",
       "1  Timed think-aloud tests; abandonment by screen...               3   \n",
       "2  Time from an inflow to the first payment vs. t...               5   \n",
       "3  Share of months with an inflow above the usual...               4   \n",
       "4  Stated belief compared with the actual withdra...               4   \n",
       "\n",
       "   severity_1_5  tractability_1_5  score_PxSxT  rank  \\\n",
       "0             5                 5           75     1   \n",
       "1             4                 5           60     2   \n",
       "2             3                 4           60     3   \n",
       "3             3                 5           60     4   \n",
       "4             4                 3           48     5   \n",
       "\n",
       "                           intervention_package  \n",
       "0  P4: Explain and reassure at the point of use  \n",
       "1                 P1: Simplify the savings path  \n",
       "2                P3: Opt-in automatic set-aside  \n",
       "3                 P2: Prompt when money arrives  \n",
       "4  P4: Explain and reassure at the point of use  "
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "barrier_register(\"en\").to_csv(\"barrier-register-en.csv\", index=False)\n",
    "barrier_register(\"fr\").to_csv(\"barrier-register-fr.csv\", index=False, encoding=\"utf-8-sig\")\n",
    "barrier_register(\"en\").head(5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "389fae73",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-11-03T16:08:23.723250Z",
     "iopub.status.busy": "2026-11-03T16:08:23.723080Z",
     "iopub.status.idle": "2026-11-03T16:08:23.728133Z",
     "shell.execute_reply": "2026-11-03T16:08:23.727232Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "All checks pass: notebook and demo agree.\n"
     ]
    }
   ],
   "source": [
    "# Headline numbers shown by the website demo at its default settings\n",
    "assert base == 20_000\n",
    "assert f.users.tolist() == [14776, 8950, 4639, 3093, 1482]\n",
    "assert ranked.id.head(5).tolist() == [\"B01\", \"B07\", \"B04\", \"B05\", \"B03\"]\n",
    "assert ranked.score.head(5).tolist() == [75, 60, 60, 60, 48]\n",
    "assert round(by_pkg.loc[\"P4\", \"share_%\"], 1) == 40.6\n",
    "assert survey_n() == 1068\n",
    "print(\"All checks pass: notebook and demo agree.\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.13.18"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
