{
"cells": [
{
"cell_type": "markdown",
"id": "99d0d245",
"metadata": {},
"source": [
"# Validation of a Surrogate Endpoint: Prentice Criteria\n",
"\n",
"
\n",
"Author: Martin Horvat, March 2026\n",
"\n",
"## Introduction\n",
"\n",
"This notebook outlines the **Prentice Criteria** (1989) for validating a surrogate endpoint ($S$) for a true clinical endpoint ($T$) in a randomized trial with treatment assignment ($Z$).\n",
"\n",
"**Variable Definitions**\n",
"* $T \\in \\{0, 1\\}$: **True Clinical Endpoint** (Binary)\n",
"* $S \\in \\mathbb{R}$: **Surrogate Endpoint** (Continuous)\n",
"* $Z \\in \\{0, 1\\}$: **Treatment Assignment** (Binary)\n",
"\n",
"Original paper was discussing binary variables $T, S, Z \\in \\{0,1\\}$\n",
"\n",
"## The Four Criteria\n",
"\n",
"To validate $S$ as a surrogate for $T$, the following probabiliy conditions must be satisfied:\n",
"\n",
"1. **Treatment Effect on True Endpoint**: The treatment must have a statistically significant impact on the true endpoint.\n",
"$$\n",
"P(T \\mid Z) \\neq P(T)\n",
"$$\n",
"The opposite is $P(T \\mid Z) = P(T)$ implying $P(T, Z) = P(T) P(Z)$, which means that $T$ and $Z$ are independent. \n",
"\n",
"2. **Treatment Effect on Surrogate**: The treatment must have a statistically significant impact on the surrogate endpoint.\n",
"$$\n",
"P(S \\mid Z) \\neq P(S)\n",
"$$\n",
"\n",
"3. **Surrogate Association with True Endpoint**: The surrogate must be significantly associated with the true endpoint.\n",
"$$\n",
"P(T \\mid S) \\neq P(T)\n",
"$$\n",
"\n",
"4. **The Specific Prentice Criterion (Full Mediation)**: The surrogate must fully capture the treatment effect on the true endpoint. \n",
"Mathematically, $T$ must be **conditionally independent** of $Z$ given $S$:\n",
"$$\n",
"P(T \\mid S, Z) = P(T \\mid S)\n",
"$$\n",
"\n",
"Ref:\n",
"- Wikipedia contributors. *Surrogate endpoint*. Wikipedia. https://en.wikipedia.org/wiki/Surrogate_endpoint\n",
"- Prentice RL. (1989). *Surrogate endpoints in clinical trials: definition and operational criteria*. *Statistics in Medicine*. DOI: 10.1002/sim.4780080407 \n",
"- Freedman LS, Graubard BI, Schatzkin A. (1992). *Statistical validation of intermediate endpoints for chronic diseases*. PMID: 1557551 \n",
"- Buyse M, Molenberghs G. (1998). *Criteria for the validation of surrogate endpoints in randomized experiments*. PMID: 9840970\n",
"- Google/DeepMind AI"
]
},
{
"cell_type": "markdown",
"id": "b4261f8d",
"metadata": {},
"source": [
"## Common"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "eba6ef4c",
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd\n",
"import numpy as np\n",
"\n",
"import matplotlib.pyplot as plt\n",
"import seaborn as sns\n",
"\n",
"import src.utils as utils\n",
"\n",
"from rich.pretty import pprint"
]
},
{
"cell_type": "markdown",
"id": "7c151183",
"metadata": {},
"source": [
"## Data"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "1338b541",
"metadata": {},
"outputs": [],
"source": [
"\"\"\"\n",
" Data interpretation:\n",
" 'Lung_SUV_95th_Percentile' ~ S or log(S)\n",
" 'Lung_AE_Flag' ~ T\n",
" 'Treatment' ~ Z\n",
"\"\"\"\n",
"\n",
"df_data, df_work = utils.read_data(\n",
" \"data/prenticedataa.xlsx\",\n",
" ['Lung_SUV_95th_Percentile', 'Lung_AE_Flag', 'Treatment'],\n",
" [\"S\", \"T\", \"Z\"],\n",
" logscale = True\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "1d533fe3",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Patient_ID | \n",
" Lung_SUV_95th_Percentile | \n",
" Bowel_SUV_95th_Percentile | \n",
" Thyroid_SUV_75th_Percentile | \n",
" Lung_AE_Flag | \n",
" Bowel_AE_Flag | \n",
" Thyroid_AE_Flag | \n",
" Treatment | \n",
"
\n",
" \n",
" \n",
" \n",
" | 0 | \n",
" 112_14 | \n",
" 2.105302 | \n",
" 2.269336 | \n",
" 2.067600 | \n",
" 1 | \n",
" 0 | \n",
" 0 | \n",
" PEMBRO | \n",
"
\n",
" \n",
" | 1 | \n",
" 1127_06 | \n",
" 1.536383 | \n",
" 5.694458 | \n",
" 3.189262 | \n",
" 0 | \n",
" 0 | \n",
" 1 | \n",
" PEMBRO | \n",
"
\n",
" \n",
" | 2 | \n",
" 1414_15 | \n",
" 1.274405 | \n",
" 2.373678 | \n",
" 1.930612 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" PEMBRO | \n",
"
\n",
" \n",
" | 3 | \n",
" 1705_16 | \n",
" 1.187935 | \n",
" 2.522945 | \n",
" 7.049728 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" PEMBRO | \n",
"
\n",
" \n",
" | 4 | \n",
" 2278_07 | \n",
" 1.674636 | \n",
" 3.006704 | \n",
" 1.587495 | \n",
" 1 | \n",
" 0 | \n",
" 0 | \n",
" PEMBRO | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Patient_ID Lung_SUV_95th_Percentile Bowel_SUV_95th_Percentile \\\n",
"0 112_14 2.105302 2.269336 \n",
"1 1127_06 1.536383 5.694458 \n",
"2 1414_15 1.274405 2.373678 \n",
"3 1705_16 1.187935 2.522945 \n",
"4 2278_07 1.674636 3.006704 \n",
"\n",
" Thyroid_SUV_75th_Percentile Lung_AE_Flag Bowel_AE_Flag Thyroid_AE_Flag \\\n",
"0 2.067600 1 0 0 \n",
"1 3.189262 0 0 1 \n",
"2 1.930612 0 0 0 \n",
"3 7.049728 0 0 0 \n",
"4 1.587495 1 0 0 \n",
"\n",
" Treatment \n",
"0 PEMBRO \n",
"1 PEMBRO \n",
"2 PEMBRO \n",
"3 PEMBRO \n",
"4 PEMBRO "
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df_data.head()"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "e130984c",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" S | \n",
" T | \n",
" Z | \n",
"
\n",
" \n",
" \n",
" \n",
" | 0 | \n",
" 0.744459 | \n",
" 1 | \n",
" 0 | \n",
"
\n",
" \n",
" | 1 | \n",
" 0.429431 | \n",
" 0 | \n",
" 0 | \n",
"
\n",
" \n",
" | 2 | \n",
" 0.242479 | \n",
" 0 | \n",
" 0 | \n",
"
\n",
" \n",
" | 3 | \n",
" 0.172217 | \n",
" 0 | \n",
" 0 | \n",
"
\n",
" \n",
" | 4 | \n",
" 0.515596 | \n",
" 1 | \n",
" 0 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" S T Z\n",
"0 0.744459 1 0\n",
"1 0.429431 0 0\n",
"2 0.242479 0 0\n",
"3 0.172217 0 0\n",
"4 0.515596 1 0"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df_work.head()"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "61ac62b4",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAA4EAAAGbCAYAAAB6eJUYAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjgsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvwVt1zgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAYjtJREFUeJzt3Xl8VOX5///37JM9YBICMYCAsiiIQkkjpWAFgrWon9q6UBURF1TccAOrBLQ/dxE/SuVTK6Ct1K0V7VcLIgUXQK241AUREESBhLBkTyaz3L8/hgwMWcg2JMO8no9HHjBn7nOf655zcq5cczaLMcYIAAAAABATrO0dAAAAAADgyKEIBAAAAIAYQhEIAAAAADGEIhAAAAAAYghFIAAAAADEEIpAAAAAAIghFIEAAAAAEEMoAgEAAAAghlAEAgAAAEAMoQgEjpCtW7fKYrFo0aJFEV1Oz549ddlll0V0GQAAAIheFIGIGIvF0qSfVatWtXeo2O+Pf/xjmxeps2bNatJ2MGrUqDZdLoDo1tFySCT2j5Hy9ddfa9asWdq6dWub992UdTJr1qw2Xy6AtmVv7wBw9PrLX/4S9vq5557T8uXL60zv37//kQzrqLdhwwZZrS37fuePf/yj0tLS2vRI4q9//Wv16dMn9Lq8vFzXXHON/ud//ke//vWvQ9O7dOnSZssEEP06Wg6JxP4xUr7++mvNnj1bo0aNUs+ePdu070M//4PNmjVLmzdvVk5OTpsuE0DbowhExFx88cVhrz/44AMtX768zvRDVVZWKj4+PpKhHdVcLld7hxBm0KBBGjRoUOj17t27dc0112jQoEGH3RYAxC5ySMfU0Of/5z//WZs3b9b111+vM8888whHBaC5OB0U7WrUqFE66aSTtG7dOv385z9XfHy87rzzTklq8JSS+q55Ky4u1k033aTs7Gy5XC716dNHDz74oAKBQJPi+Ne//qURI0YoISFBSUlJOuuss/TVV1+FtbnsssuUmJio7du369xzz1ViYqLS09N16623yu/314nnsssuU0pKilJTUzVx4kQVFxfXWW5tn999953y8vKUkJCgbt266Z577pExJqxtRUWFbrnlltAY+/btq0ceeaROu0M/n0WLFslisWj16tWaNm2a0tPTlZCQoP/5n/9RUVFR2HxfffWV3nnnHU7RBBAVGsshHo9H+fn56tOnj1wul7Kzs3X77bfL4/GE9bFw4UL94he/UEZGhlwulwYMGKCnnnoqrE1j+8fafez777+vG264Qenp6UpNTdXVV1+tmpoaFRcX69JLL1WnTp3UqVMn3X777XX224FAQHPnztWJJ54ot9utLl266Oqrr9a+ffvqxPGrX/1K77//voYNGya3261evXrpueeeC7VZtGiRfvvb30qSTj/99CNy2uxXX32lG264QaeccooefvjhiC0HQNvhSCDa3Z49e3TmmWfqwgsv1MUXX9zs0wIrKys1cuRIbd++XVdffbW6d++uNWvWaMaMGdq5c6fmzp3b6Px/+ctfNHHiROXl5enBBx9UZWWlnnrqKf3sZz/Tp59+GnYqjd/vV15ennJycvTII4/o7bff1qOPPqrevXvrmmuukSQZY3TOOefo/fff15QpU9S/f3+9+uqrmjhxYr3L9/v9GjdunH7605/qoYce0tKlS5Wfny+fz6d77rkn1OfZZ5+tlStXavLkyRo8eLCWLVum2267Tdu3b9djjz122M/p+uuvV6dOnZSfn6+tW7dq7ty5mjp1ql588UVJ0ty5c3X99dcrMTFRv//97yVxiiaAjq++HBIIBHT22Wfr/fff11VXXaX+/fvriy++0GOPPaZvv/1WS5YsCc3/1FNP6cQTT9TZZ58tu92uf/7zn7r22msVCAR03XXXSWra/vH6669XZmamZs+erQ8++EB/+tOflJqaqjVr1qh79+6677779Oabb+rhhx/WSSedpEsvvTQ079VXX61FixZp0qRJuuGGG7RlyxY9+eST+vTTT7V69Wo5HI5Q202bNuk3v/mNJk+erIkTJ2rBggW67LLLNGTIEJ144on6+c9/rhtuuEH/+7//qzvvvDN0umykTputrKzU+eefL5vNphdeeKHDnY0CoAEGOEKuu+46c+gmN3LkSCPJzJ8/v057SSY/P7/O9B49epiJEyeGXt97770mISHBfPvtt2Htpk+fbmw2m9m2bVuDMZWVlZnU1FRz5ZVXhk0vKCgwKSkpYdMnTpxoJJl77rknrO0pp5xihgwZEnq9ZMkSI8k89NBDoWk+n8+MGDHCSDILFy6s0+f1118fmhYIBMxZZ51lnE6nKSoqCuvzD3/4Q9iyf/Ob3xiLxWI2bdrU4OezcOFCI8mMHj3aBAKB0PSbb77Z2Gw2U1xcHJp24oknmpEjRzb4ebWFoqKiBtctADSkOTnkL3/5i7Farea9994Lmz5//nwjyaxevTo0rbKyss6y8vLyTK9evcKmNbR/rN3H5uXlhe1jc3NzjcViMVOmTAlN8/l85thjjw3r57333jOSzPPPPx/W79KlS+tM79Gjh5Fk3n333dC0Xbt2GZfLZW655ZbQtJdfftlIMitXrqwTb1u7/PLLjSTz7LPPRnxZANoOp4Oi3blcLk2aNKnF87/88ssaMWKEOnXqpN27d4d+Ro8eLb/fr3fffbfBeZcvX67i4mJddNFFYfPabDbl5ORo5cqVdeaZMmVK2OsRI0bou+++C71+8803ZbfbQ0cGJclms+n6669vMI6pU6eG/m+xWDR16lTV1NTo7bffDvVps9l0ww03hM13yy23yBijf/3rXw32Xeuqq66SxWIJi9vv9+v7778/7LwA0FHVl0Nefvll9e/fX/369Qvbt//iF7+QpLB9e1xcXOj/JSUl2r17t0aOHKnvvvtOJSUlTY5j8uTJYfvYnJwcGWM0efLk0DSbzaahQ4eG5YyXX35ZKSkpGjNmTFisQ4YMUWJiYp08NGDAAI0YMSL0Oj09XX379g3r80hZvHixFixYoEsuuSTsyCaAjo/TQdHusrKy5HQ6Wzz/xo0b9d///lfp6en1vr9r165G55UU+sPgUMnJyWGv3W53neV06tQp7LqN77//Xl27dlViYmJYu759+9a7DKvVql69eoVNO+GEEyQpdHvv77//Xt26dVNSUlJYu9rTe5pSyHXv3r1O3JLqXHPSVEVFRWHXQiYmJtYZMwBEWn05ZOPGjVq/fn2T8sLq1auVn5+vtWvXqrKyMqxdSUmJUlJSmhTHofvY2vmys7PrTD94v7tx40aVlJQoIyPjsLHWtxypbh5qjqqqqjrFbmZm5mHn27hxo6ZMmaITTjhBf/zjH1u0bADthyIQ7e7gb2Gb4tCbsAQCAY0ZM0a33357ve1rC6r61N445i9/+Uu9Sc9uD/8VsdlszYq1I2kodnPIDQqa6ic/+UlY8Zmfn8+zoQAccfXlkEAgoIEDB2rOnDn1zlNbmG3evFlnnHGG+vXrpzlz5ig7O1tOp1NvvvmmHnvssSbfXExqeB9b3/SD97uBQEAZGRl6/vnn653/0EK2rfflL774Yp0jqYfry+Px6IILLlBNTY1eeOEFvgAEohBFIDqsTp061bmjZk1NjXbu3Bk2rXfv3iovL9fo0aObvYzevXtLkjIyMlo0f3169OihFStWqLy8PCwxbtiwod72gUBA3333XVix+u2330pS6KY0PXr00Ntvv62ysrKwo4HffPNN6P22cPCpTIfz/PPPq6qqKvT60KOZANBeevfurc8//1xnnHFGo/u1f/7zn/J4PHr99dfDjrDVdylAc/aPzY317bff1vDhw5v9pWhDmhNrXl6eli9f3qz+b731Vn366ad6/PHHdcoppzQ3PAAdANcEosPq3bt3nev5/vSnP9U5Enj++edr7dq1WrZsWZ0+iouL5fP5GlxGXl6ekpOTdd9998nr9dZ5/+BHKDTVL3/5S/l8vrBbjPv9fj3xxBMNzvPkk0+G/m+M0ZNPPimHw6Ezzjgj1Kff7w9rJ0mPPfaYLBZLmz2TKSEhod5HWdRn+PDhGj16dOiHIhBAR3H++edr+/btevrpp+u8V1VVpYqKCkkHjqodfOSrpKRECxcurDNfc/aPzY3V7/fr3nvvrfOez+dr0TITEhIkqUnzdu3aNWxffrgvRF999VU9+eSTOvvss+tcpw4genAkEB3WFVdcoSlTpui8887TmDFj9Pnnn2vZsmVKS0sLa3fbbbfp9ddf169+9avQbbIrKir0xRdf6JVXXtHWrVvrzFMrOTlZTz31lC655BKdeuqpuvDCC5Wenq5t27bpjTfe0PDhw+sUXoczfvx4DR8+XNOnT9fWrVs1YMAA/eMf/2jwBgNut1tLly7VxIkTlZOTo3/961964403dOedd4ZOAxo/frxOP/10/f73v9fWrVt18skn66233tJrr72mm266KXREs7WGDBmip556Sn/4wx/Up08fZWRkNHi9JAB0VJdccoleeuklTZkyRStXrtTw4cPl9/v1zTff6KWXXtKyZcs0dOhQjR07Vk6nU+PHj9fVV1+t8vJyPf3008rIyKhz1kmk9o8jR47U1Vdfrfvvv1+fffaZxo4dK4fDoY0bN+rll1/W448/rt/85jfN6nPw4MGy2Wx68MEHVVJSIpfLFXoWYmvs3LlTkydPls1m0xlnnKG//vWv9bbr3bu3cnNzW7UsAJFFEYgO68orr9SWLVv0zDPPaOnSpRoxYoSWL18eOjpWKz4+Xu+8847uu+8+vfzyy3ruueeUnJysE044QbNnzz7s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AICk8ePHa9y4cfW+995778lisei///3vEY6q7VEEAgAAAICkyZMna/ny5frxxx/rvLdw4UINHTpUgwYNaofI2hZFIAAAAABI+tWvfqX09HQtWrQobHp5eblefvllnXvuubrooouUlZWl+Ph4DRw4UH/7298a7dNisWjJkiVh01JTU8OW8cMPP+j8889XamqqOnfurHPOOUdbt25tm0HVgyIQAAAAACTZ7XZdeumlWrRokYwxoekvv/yy/H6/Lr74Yg0ZMkRvvPGGvvzyS1111VW65JJL9NFHH7V4mV6vV3l5eUpKStJ7772n1atXKzExUePGjVNNTU1bDKsOikAAAAAA2O/yyy/X5s2b9c4774SmLVy4UOedd5569OihW2+9VYMHD1avXr10/fXXa9y4cXrppZdavLwXX3xRgUBAf/7znzVw4ED1799fCxcu1LZt27Rq1ao2GFFdFIEAAAAAsF+/fv102mmnacGCBZKkTZs26b333tPkyZPl9/t17733auDAgercubMSExO1bNkybdu2rcXL+/zzz7Vp0yYlJSUpMTFRiYmJ6ty5s6qrq7V58+a2GlYYe0R6BQAAAIAoNXnyZF1//fWaN2+eFi5cqN69e2vkyJF68MEH9fjjj2vu3LkaOHCgEhISdNNNNzV62qbFYgk7tVQKngJaq7y8XEOGDNHzzz9fZ9709PS2G9RBKAIBAAAA4CDnn3++brzxRi1evFjPPfecrrnmGlksFq1evVrnnHOOLr74YklSIBDQt99+qwEDBjTYV3p6unbu3Bl6vXHjRlVWVoZen3rqqXrxxReVkZGh5OTkyA3qIJwOCgAAAAAHSUxM1AUXXKAZM2Zo586duuyyyyRJxx9/vJYvX641a9Zo/fr1uvrqq1VYWNhoX7/4xS/05JNP6tNPP9XHH3+sKVOmyOFwhN7/3e9+p7S0NJ1zzjl67733tGXLFq1atUo33HBDvY+qaAsUgQAAAABwiMmTJ2vfvn3Ky8tTt27dJEl33XWXTj31VOXl5WnUqFHKzMzUueee22g/jz76qLKzszVixAhNmDBBt956q+Lj40Pvx8fH691331X37t3161//Wv3799fkyZNVXV0dsSODnA4KAAAAAIfIzc2tcy1f586d6zzz71CH3tGzW7duWrZsWdi04uLisNeZmZl69tlnWxpqs3EkEAAAAABiCEUgAAAAAMQQikAAAAAAiCEUgQAAAAAQQygCAQAAACCGUAQCAAAAQAyhCAQAAACAGEIRCAAAAAAxhCIQAAAAAGIIRSAAAAAAxBCKQAAAAADooObNm6eePXvK7XYrJydHH330Uav7pAgEAAAAgMMIBIx+2FupbwpK9cPeSgUCJuLLfPHFFzVt2jTl5+frk08+0cknn6y8vDzt2rWrVf3a2yg+AAAAADgqbdpVpmVfFmpzUbmqfX657Tb1Tk9U3kld1CcjKWLLnTNnjq688kpNmjRJkjR//ny98cYbWrBggaZPn97ifjkSCAAAAAAN2LSrTAtXb9WXO0qUGu9Qr7REpcY79OWOEi1cvVWbdpVFZLk1NTVat26dRo8eHZpmtVo1evRorV27tlV9UwQCAAAAQD0CAaNlXxZqb0WNjs9IVJLbIZvVoiS3Q8dnJGpvRY3e+qowIqeG7t69W36/X126dAmb3qVLFxUUFLSqb4pAAAAAAKjH9uIqbS4qV9cUtywWS9h7FotFXVPc2rSrXNuLq9opwpahCAQAAACAelTU+FTt8yveWf+tVOKcNnl8flXU+Np82WlpabLZbCosLAybXlhYqMzMzFb1TREIAAAAAPVIcNrltttU2UCRV1Xjl8tuU0IDRWJrOJ1ODRkyRCtWrAhNCwQCWrFihXJzc1vVN3cHBQAAAIB6ZKXGqXd6or7cUaJElz3slFBjjHaWVGtgVoqyUuMisvxp06Zp4sSJGjp0qIYNG6a5c+eqoqIidLfQlqIIBAAAAIB6WK0W5Z3URTtKqrRxV/DawDinTVU1fu0sqVbnBKfGnthFVqvl8J21wAUXXKCioiLNnDlTBQUFGjx4sJYuXVrnZjHNRREIAAAAAA3ok5GkScN7hp4TWFhaLZfdpoFZKRp7YmSfEyhJU6dO1dSpU9u0T4pAAAAAAGhEn4wk9RqVqO3FVaqo8SnBaVdWalzEjgBGGkUgAAAAAByG1WpRduf49g6jTXB3UAAAAACIIRSBAAAAABBDKAIBAAAAIIZQBAIAAABADKEIBAAAAIAYQhEIAAAAADGEIhAAAAAAYghFIAAAAADEkBYVgfPmzVPPnj3ldruVk5Ojjz76qEnzvfDCC7JYLDr33HNbslgAAAAAaB+BgLTve6nwq+C/gUDEF/nuu+9q/Pjx6tatmywWi5YsWdIm/dqbO8OLL76oadOmaf78+crJydHcuXOVl5enDRs2KCMjo8H5tm7dqltvvVUjRoxoVcAAAAAAcEQVbZDW/1PavVHyVUt2t5R2vNR/vJTeN2KLraio0Mknn6zLL79cv/71r9us32YXgXPmzNGVV16pSZMmSZLmz5+vN954QwsWLND06dPrncfv9+t3v/udZs+erffee0/FxcWNLsPj8cjj8YRel5aWSpK8Xq+8Xm9zQw6pnbc1fbSnaI9fiv4xRHv8EmPoCKI9finysZMHGhbtY4j2+CXG0BFEe/xS9I8h2uNvlqIN0gfzpco9UkqW5EiQvBXSzv9KJduln06JWCF45pln6swzz2zzfi3GGNPUxjU1NYqPj9crr7wSdkrnxIkTVVxcrNdee63e+fLz8/Xf//5Xr776qi677DIVFxc3eihz1qxZmj17dp3pixcvVnx8fFPDBQBEUGVlpSZMmKCSkhIlJye3ad/kAQCIDpHMBW2lurpaW7Zs0XHHHSe32928mQMB6f05wYIvvZ9ksRx4zxip6Bup28nS8Jsla2Rvt2KxWPTqq682emldU8farCOBu3fvlt/vV5cuXcKmd+nSRd98802987z//vt65pln9NlnnzV5OTNmzNC0adNCr0tLS5Wdna2xY8e2auPyer1avny5xowZI4fD0eJ+2ku0xy9F/xiiPX6JMXQE0R6/FBxDQ1/8tQXyQMOifQzRHr/EGDqCaI9fiv4x1MZ/+umnt3cokVXyQ/AU0JSs8AJQCr5OzpKKvg2269SjfWJsgWafDtocZWVluuSSS/T0008rLS2tyfO5XC65XK460x0OR5v8krRVP+0l2uOXon8M0R6/xBg6gmiPP5LIA4cX7WOI9vglxtARRHv8UvSPIZpjb5Ka8uA1gI6E+t93xktlO4LtokizisC0tDTZbDYVFhaGTS8sLFRmZmad9ps3b9bWrVs1fvz40LTA/rvo2O12bdiwQb17925J3AAAAAAQWc7E4E1gvBWSq54zUWoqg+87E498bK3QrBNXnU6nhgwZohUrVoSmBQIBrVixQrm5uXXa9+vXT1988YU+++yz0M/ZZ5+t008/XZ999pmys7NbPwIAAAAAiISU7OBdQEu2B68BPJgxUul2Kf2EYLso0uzTQadNm6aJEydq6NChGjZsmObOnauKiorQ3UIvvfRSZWVl6f7775fb7dZJJ50UNn9qaqok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q6++2mj77777zsTHx5tp06aZr7/+2jzxxBPGZrOZpUuXhto09zM5kvHfeOON5sEHHzQfffSR+fbbb82MGTOMw+Ewn3zySahNfn6+OfHEE8M+/6KiojaPvaVjWLlypZFkNmzYEBaj3+8PtTmS6+Bg5IGOvw/qaLmAPEAeaI8xdLRccDTlATTNUVMEfv3110aS+c9//hOa9q9//ctYLBazffv2Jvfz0ksvGafTabxeb2haU34ZWmLYsGHmuuuuC732+/2mW7du5v7776+3/fnnn2/OOuussGk5OTnm6quvNsYYEwgETGZmpnn44YdD7xcXFxuXy2X+9re/tXv8h/L5fCYpKck8++yzoWkTJ04055xzTluH2qDmjmHhwoUmJSWlwf6O9DowpvXr4bHHHjNJSUmmvLw8NO1Ir4daTfldu/32282JJ54YNu2CCy4weXl5odet/UxaqqX7igEDBpjZs2eHXufn55uTTz657QJrhuYk/3379jXYpj3WAXkgOvdB7Z0LyAPkgbYW7bkgmvMAmu6oOR107dq1Sk1N1dChQ0PTRo8eLavVqg8//LDJ/ZSUlCg5OVl2uz1s+nXXXae0tDQNGzZMCxYskGnl4xVramq0bt06jR49OjTNarVq9OjRWrt2bb3zrF27Nqy9JOXl5YXab9myRQUFBWFtUlJSlJOT02CfRzL+Q1VWVsrr9apz585h01etWqWMjAz17dtX11xzjfbs2dOmsddq6RjKy8vVo0cPZWdn65xzztFXX30Veu9IroPWjOFgzzzzjC688EIlJCSETT9S66G5Dvd70BafyZEUCARUVlZW5/dg48aN6tatm3r16qXf/e532rZtWztF2LDBgwera9euGjNmjFavXh2a3l7rgDwQnfug9swF5IEg8kD7i9Zc0NHyAJruqCkCCwoKlJGRETbNbrerc+fOdc5Pbsju3bt177336qqrrgqbfs899+ill17S8uXLdd555+naa6/VE0880ap4d+/eLb/fry5duoRN79KlS4PxFhQUNNq+9t/m9NlSLYn/UHfccYe6desWtoMYN26cnnvuOa1YsUIPPvig3nnnHZ155pny+/1tGr/UsjH07dtXCxYs0Guvvaa//vWvCgQCOu200/Tjjz9KOrLroKVjONhHH32kL7/8UldccUXY9CO5Hpqrod+D0tJSVVVVtcm2eSQ98sgjKi8v1/nnnx+alpOTo0WLFmnp0qV66qmntGXLFo0YMUJlZWXtGOkBXbt21fz58/X3v/9df//735Wdna1Ro0bpk08+kdQ2+4eWIA9E3z5Iat9cQB4gD3QU0ZYLOmoeQNPZD9+kfU2fPl0PPvhgo23Wr1/f6uWUlpbqrLPO0oABAzRr1qyw9+6+++7Q/0855RRVVFTo4Ycf1g033NDq5caqBx54QC+88IJWrVoVdkH9hRdeGPr/wIEDNWjQIPXu3VurVq3SGWec0R6hhsnNzVVubm7o9Wmnnab+/fvr//7v/3Tvvfe2Y2Qt88wzz2jgwIEaNmxY2PSOvh6OFosXL9bs2bP12muvhRUvZ555Zuj/gwYNUk5Ojnr06KGXXnpJkydPbo9Qw/Tt21d9+/YNvT7ttNO0efNmPfbYY/rLX/7S5ssjDxy9ojEXkAfafx0cbaIxFxzpPIC21+GPBN5yyy1av359oz+9evVSZmamdu3aFTavz+fT3r17lZmZ2egyysrKNG7cOCUlJenVV1+Vw+FotH1OTo5+/PFHeTyeFo8rLS1NNptNhYWFYdMLCwsbjDczM7PR9rX/NqfPlmpJ/LUeeeQRPfDAA3rrrbc0aNCgRtv26tVLaWlp2rRpU6tjPlRrxlDL4XDolFNOCcV3JNeB1LoxVFRU6IUXXmhSIonkemiuhn4PkpOTFRcX1ybr9Uh44YUXdMUVV+ill16qc1rToVJTU3XCCSd0iM+/IcOGDQvF19brgDxwQEfKA1L05wLyAHmgvR1NuSCSeQBtr8MXgenp6erXr1+jP06nU7m5uSouLta6detC8/773/9WIBBQTk5Og/2XlpZq7Nixcjqdev311+vc5rk+n332mTp16iSXy9XicTmdTg0ZMkQrVqwITQsEAlqxYkXYN4wHy83NDWsvScuXLw+1P+6445SZmRnWprS0VB9++GGDfR7J+CXpoYce0r333qulS5eGXbfTkB9//FF79uxR165d2yTug7V0DAfz+/364osvQvEdyXUgtW4ML7/8sjwejy6++OLDLieS66G5Dvd70BbrNdL+9re/adKkSfrb3/4Wdkv2hpSXl2vz5s0d4vNvyGeffRaKr63XAXnggI6UB1o6Bqnj5ALyAHmgPR1tuSCSeQAR0N53pmlL48aNM6eccor58MMPzfvvv2+OP/74sFuD//jjj6Zv377mww8/NMYYU1JSYnJycszAgQPNpk2bwm5x6/P5jDHGvP766+bpp582X3zxhdm4caP54x//aOLj483MmTNbHe8LL7xgXC6XWbRokfn666/NVVddZVJTU0O3mr7kkkvM9OnTQ+1Xr15t7Ha7eeSRR8z69etNfn5+vbcGT01NNa+99pr573//a84555yIPiKiOfE/8MADxul0mldeeSXssy4rKzPGGFNWVmZuvfVWs3btWrNlyxbz9ttvm1NPPdUcf/zxprq6us3jb8kYZs+ebZYtW2Y2b95s1q1bZy688ELjdrvNV199FTbOI7UOWjKGWj/72c/MBRdcUGf6kV4PZWVl5tNPPzWffvqpkWTmzJljPv30U/P9998bY4yZPn26ueSSS0Lta28Nftttt5n169ebefPm1Xtr8MY+k/aM//nnnzd2u93Mmzcv7PeguLg41OaWW24xq1atMlu2bDGrV682o0ePNmlpaWbXrl1tHn9LxvDYY4+ZJUuWmI0bN5ovvvjC3HjjjcZqtZq333471OZIroODkQc6/j6oo+UC8gB5oD3G0NFywdGUB9A0R1URuGfPHnPRRReZxMREk5ycbCZNmhRKKsYYs2XLFiPJrFy50hhz4Pa29f1s2bLFGBO8vfjgwYNNYmKiSUhIMCeffLKZP39+2HNQWuOJJ54w3bt3N06n0wwbNsx88MEHofdGjhxpJk6cGNb+pZdeMieccIJxOp3mxBNPNG+88UbY+4FAwNx9992mS5cuxuVymTPOOMNs2LChTWJtbfw9evSo97POz883xhhTWVlpxo4da9LT043D4TA9evQwV155ZcR3Fs0Zw0033RRq26VLF/PLX/4y7Jk+xhz5ddDcMRhjzDfffGMkmbfeeqtOX0d6PTT0e1gb88SJE83IkSPrzDN48GDjdDpNr169wp5tVauxz6Q94x85cmSj7Y0J3uq8a9euxul0mqysLHPBBReYTZs2RST+lozhwQcfNL179zZut9t07tzZjBo1yvz73/+u0++RWgcHIw90/H1QR8wF5IFw5IHIj6Gj5YKjKQ+gaSzGtPIe1wAAAACAqNHhrwkEAAAAALQdikAAAAAAiCEUgQAAAAAQQygCAQAAACCGUAQCAAAAQAyhCAQAAACAGEIRCAAAAAAxhCIQAAAAAGIIRSAAAAAAxBCKQES9oqIiXXPNNerevbtcLpcyMzOVl5en1atXt3dorbJq1SpZLBYVFxcfkeVVVlZqxowZ6t27t9xut9LT0zVy5Ei99tprR2T5ANAa5IK2QS4AYoO9vQMAWuu8885TTU2Nnn32WfXq1UuFhYVasWKF9uzZ0+I+jTHy+/2y28N/RWpqauR0Olsbcoc0ZcoUffjhh3riiSc0YMAA7dmzR2vWrGnV5wgARwq5oG2QC4AYYYAotm/fPiPJrFq1qsE2W7ZsMZLMp59+Wme+lStXGmOMWblypZFk3nzzTXPqqacah8NhVq5caUaOHGmuu+46c+ONN5pjjjnGjBo1yhhjzKpVq8xPfvIT43Q6TWZmprnjjjuM1+sN9V9aWmomTJhg4uPjTWZmppkzZ44ZOXKkufHGG0NtnnvuOTNkyBCTmJhounTpYi666CJTWFgYFvPBPxMnTjTGGOP3+819991nevbsadxutxk0aJB5+eWXW/1ZpqSkmEWLFrW6HwA40sgF5AIAzcPpoIhqiYmJSkxM1JIlS+TxeFrd3/Tp0/XAAw9o/fr1GjRokCTp2WefldPp1OrVqzV//nxt375dv/zlL/WTn/xEn3/+uZ566ik988wz+sMf/hDqZ9q0aVq9erVef/11LV++XO+9954++eSTsGV5vV7de++9+vzzz7VkyRJt3bpVl112mSQpOztbf//73yVJGzZs0M6dO/X4449Lku6//34999xzmj9/vr766ivdfPPNuvjii/XOO++0auyZmZl68803VVZW1qp+AOBIIxeQCwA0U3tXoUBrvfLKK6ZTp07G7Xab0047zcyYMcN8/vnnofeb8+3vkiVLwvoeOXKkOeWUU8Km3XnnnaZv374mEAiEps2bN88kJiYav99vSktLjcPhCPtGtri42MTHx4d9+3uo//znP0aSKSsrC4tp3759oTbV1dUmPj7erFmzJmzeyZMnm4suuqjRz+lw3nnnHXPssccah8Nhhg4dam666Sbz/vvvt6pPADhSyAXkAgBNx5FARL3zzjtPO3bs0Ouvv65x48Zp1apVOvXUU7Vo0aJm9zV06NA604YMGRL2ev369crNzZXFYglNGz58uMrLy/Xjjz/qu+++k9fr1bBhw0Lvp6SkqG/fvmH9rFu3TuPHj1f37t2VlJSkkSNHSpK2bdvWYHybNm1SZWWlxowZE/rmOzExUc8995w2b95c7zz33XdfWNuG+v/5z3+u7777TitWrNBvfvMbffXVVxoxYoTuvffeBuMBgI6CXEAuANB03BgGRwW3260xY8ZozJgxuvvuu3XFFVcoPz9fl112mazW4HcdxphQe6/XW28/CQkJTZrWWhUVFcrLy1NeXp6ef/55paena9u2bcrLy1NNTU2D85WXl0uS3njjDWVlZYW953K56p1nypQpOv/880Ovu3Xr1mD/DodDI0aM0IgRI3THHXfoD3/4g+655x7dcccdR+1NEAAcPcgF5AIATUMRiKPSgAEDtGTJEklSenq6JGnnzp065ZRTJEmfffZZi/vu37+//v73v8sYE/oGePXq1UpKStKxxx6rTp06yeFw6D//+Y+6d+8uSSopKdG3336rn//855Kkb775Rnv27NEDDzyg7OxsSdLHH38ctpzaROv3+8PG5XK5tG3bttC3xYfTuXNnde7cuUVjHTBggHw+n6qrq0n8AKIOueAAcgGAg1EEIqrt2bNHv/3tb3X55Zdr0KBBSkpK0scff6yHHnpI55xzjiQpLi5OP/3pT/XAAw/ouOOO065du3TXXXe1eJnXXnut5s6dq+uvv15Tp07Vhg0blJ+fr2nTpslqtSopKUkTJ07Ubbfdps6dOysjI0P5+fmyWq2hPxS6d+8up9OpJ554QlOmTNGXX35Z51SbHj16yGKx6P/9v/+nX/7yl4qLi1NSUpJuvfVW3XzzzQoEAvrZz36mkpISrV69WsnJyZo4cWKLxzVq1ChddNFFGjp0qI455hh9/fXXuvPOO3X66acrOTm5xf0CQKSRC8gFAJqpfS9JBFqnurraTJ8+3Zx66qkmJSXFxMfHm759+5q77rrLVFZWhtp9/fXXJjc318TFxZnBgwebt956q96bARx84b0xps6tvGu15Lbgw4YNM9OnTw+1Wbx4senZs6dxuVwmNzfXvP7663VuWnDPPfeYzMxMY7FYQrcFDwQCZu7cuaZv377G4XCY9PR0k5eXZ955551WfZb33Xefyc3NNZ07dzZut9v06tXL3HDDDWb37t2t6hcAIo1cQC4A0DwWYw46OR5ARFRUVCgrK0uPPvqoJk+e3N7hAADaAbkAQEfB6aBABHz66af65ptvNGzYMJWUlOiee+6RpNBpSQCAox+5AEBHRREIRMgjjzyiDRs2yOl0asiQIXrvvfeUlpbW3mEBAI4gcgGAjojTQQEAAAAghvCweAAAAACIIRSBAAAAABBDKAIBAAAAIIZQBAIAAABADKEIBAAAAIAYQhEIAAAAADGEIhAAAAAAYghFIAAAAADEkP8f5ba28PP5BTQAAAAASUVORK5CYII=",
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"fig, axs = plt.subplots(ncols=2, figsize =(8,4), layout = \"constrained\", sharey=True)\n",
"\n",
"for ax, lab, name in zip(axs, [\"T\",\"Z\"], [\"True endpoint\", \"Treatment\"]):\n",
" \n",
" for val in [0,1]:\n",
" mask = df_work[lab] == val\n",
" ax.scatter(df_work[\"S\"][mask], df_work[lab][mask], label=f\"{val}\", alpha=0.5)\n",
" \n",
" ax.grid()\n",
" ax.set_xlabel(\"Surrogate - S\")\n",
" #ax.set_ylabel(f\"{name} - {lab}\")\n",
" ax.set_title(f\"{name} - {lab}\")\n",
"\n",
"# build one shared legend, positioned to the right of the right subplot\n",
"handles, labels = axs[0].get_legend_handles_labels()\n",
"fig.legend(handles, labels, loc=\"center left\", bbox_to_anchor=(1.02, 0.5), title=\"Value\")\n",
"\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"id": "6c1f4f8a",
"metadata": {},
"source": [
"## Discussing first Prentice criteria"
]
},
{
"cell_type": "markdown",
"id": "8513d6c4-8047-447a-9163-351e269d5950",
"metadata": {},
"source": [
"### T-Z statistics"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "0adcb6fe",
"metadata": {},
"outputs": [],
"source": [
"rTZ = utils.tz_analysis(df_work, \"T\", \"Z\")"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "f88fd897",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Counts F=\n"
]
},
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" 0 | \n",
" 1 | \n",
"
\n",
" \n",
" \n",
" \n",
" | 0 | \n",
" 47 | \n",
" 6 | \n",
"
\n",
" \n",
" | 1 | \n",
" 4 | \n",
" 1 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" 0 1\n",
"0 47 6\n",
"1 4 1"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Probabilities P(T,Z)=\n"
]
},
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" 0 | \n",
" 1 | \n",
"
\n",
" \n",
" \n",
" \n",
" | 0 | \n",
" 0.810345 | \n",
" 0.103448 | \n",
"
\n",
" \n",
" | 1 | \n",
" 0.068966 | \n",
" 0.017241 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" 0 1\n",
"0 0.810345 0.103448\n",
"1 0.068966 0.017241"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"image/png": "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",
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# Contingency table \n",
"print(\"Counts F =\")\n",
"display(pd.DataFrame(rTZ[\"counts\"][\"F\"]))\n",
"\n",
"# Probabilities\n",
"print(\"Probabilities P(T,Z) =\")\n",
"prob = rTZ[\"probabilities\"]\n",
"display(pd.DataFrame(prob[\"P_TZ\"]))\n",
"\n",
"# Create the heatmap for 2x2 Contingency Table\n",
"plt.figure(figsize=(6, 5))\n",
"sns.heatmap(rTZ[\"counts\"][\"F\"], \n",
" annot=True, # Show the numbers in the cells\n",
" fmt='d', # Use integer formatting\n",
" cmap='YlGnBu', # Color scheme (Yellow-Green-Blue)\n",
" xticklabels= [\"0\", \"1\"], \n",
" yticklabels= [\"0\", \"1\"],)\n",
"\n",
"plt.xlabel('T')\n",
"plt.ylabel('Z')\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "d9d2aa8c",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"P(T) = [0.9137931 0.0862069]\n",
"P(Z) = [0.87931034 0.12068966]\n"
]
}
],
"source": [
"# Marginal probabilities \n",
"print(f\"P(T) = {prob['P_T']}\")\n",
"print(f\"P(Z) = {prob['P_Z']}\")"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "42f7d99e",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"P(T|Z)=\n"
]
},
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" 0 | \n",
" 1 | \n",
"
\n",
" \n",
" \n",
" \n",
" | 0 | \n",
" 0.921569 | \n",
" 0.857143 | \n",
"
\n",
" \n",
" | 1 | \n",
" 0.078431 | \n",
" 0.142857 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" 0 1\n",
"0 0.921569 0.857143\n",
"1 0.078431 0.142857"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"print(\"Conditional probabilities P(T|Z) =\")\n",
"pd.DataFrame(prob[\"P_T_given_Z\"])"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "5c1118e2",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"P(T|Z) - P(T) =\n"
]
},
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" 0 | \n",
" 1 | \n",
"
\n",
" \n",
" \n",
" \n",
" | 0 | \n",
" 0.007776 | \n",
" -0.05665 | \n",
"
\n",
" \n",
" | 1 | \n",
" -0.007776 | \n",
" 0.05665 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" 0 1\n",
"0 0.007776 -0.05665\n",
"1 -0.007776 0.05665"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"P(T|Z)/P(T) - 1 1^T =\n"
]
},
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" 0 | \n",
" 1 | \n",
"
\n",
" \n",
" \n",
" \n",
" | 0 | \n",
" 0.008509 | \n",
" -0.061995 | \n",
"
\n",
" \n",
" | 1 | \n",
" -0.090196 | \n",
" 0.657143 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" 0 1\n",
"0 0.008509 -0.061995\n",
"1 -0.090196 0.657143"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# Difference between Prob_T_at_Z and Prob_T\n",
"prob = rTZ[\"probabilities\"]\n",
"print(\"Differences: P(T|Z) - P(T) =\")\n",
"display(pd.DataFrame(prob[\"P_T_given_Z\"] - prob[\"P_T\"][:, None]))\n",
"\n",
"print(\"Differences: P(T|Z)/P(T) - 1 1^T =\")\n",
"display(pd.DataFrame(prob[\"P_T_given_Z\"]/prob[\"P_T\"][:,None] - np.ones(shape = (2,2))))"
]
},
{
"cell_type": "markdown",
"id": "9c2af5bc-b65c-4ff5-9991-714dd4ee9172",
"metadata": {},
"source": [
"### Tests results"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "60014129",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"{\n",
"│ 'stat': 0.3243168965699486,\n",
"│ 'dof': 1,\n",
"│ 'pvalue': 0.569024824759762,\n",
"│ 'expected': array([[46.60344828, 6.39655172],\n",
"│ [ 4.39655172, 0.60344828]]),\n",
"│ 'reject_alpha': False\n",
"}\n",
"\n"
],
"text/plain": [
"\u001b[1m{\u001b[0m\n",
"\u001b[2;32m│ \u001b[0m\u001b[32m'stat'\u001b[0m: \u001b[1;36m0.3243168965699486\u001b[0m,\n",
"\u001b[2;32m│ \u001b[0m\u001b[32m'dof'\u001b[0m: \u001b[1;36m1\u001b[0m,\n",
"\u001b[2;32m│ \u001b[0m\u001b[32m'pvalue'\u001b[0m: \u001b[1;36m0.569024824759762\u001b[0m,\n",
"\u001b[2;32m│ \u001b[0m\u001b[32m'expected'\u001b[0m: \u001b[1;35marray\u001b[0m\u001b[1m(\u001b[0m\u001b[1m[\u001b[0m\u001b[1m[\u001b[0m\u001b[1;36m46.60344828\u001b[0m, \u001b[1;36m6.39655172\u001b[0m\u001b[1m]\u001b[0m,\n",
"\u001b[2;32m│ \u001b[0m\u001b[1m[\u001b[0m \u001b[1;36m4.39655172\u001b[0m, \u001b[1;36m0.60344828\u001b[0m\u001b[1m]\u001b[0m\u001b[1m]\u001b[0m\u001b[1m)\u001b[0m,\n",
"\u001b[2;32m│ \u001b[0m\u001b[32m'reject_alpha'\u001b[0m: \u001b[3;91mFalse\u001b[0m\n",
"\u001b[1m}\u001b[0m\n"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# Pearson chi-square test\n",
"pprint(rTZ[\"global_tests\"][\"chi2\"])"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "eca15f98",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"{\n",
"│ 'odds_ratio': 1.9583333333333333,\n",
"│ 'pvalue': 0.48734165612568525,\n",
"│ 'reject_alpha': False\n",
"}\n",
"\n"
],
"text/plain": [
"\u001b[1m{\u001b[0m\n",
"\u001b[2;32m│ \u001b[0m\u001b[32m'odds_ratio'\u001b[0m: \u001b[1;36m1.9583333333333333\u001b[0m,\n",
"\u001b[2;32m│ \u001b[0m\u001b[32m'pvalue'\u001b[0m: \u001b[1;36m0.48734165612568525\u001b[0m,\n",
"\u001b[2;32m│ \u001b[0m\u001b[32m'reject_alpha'\u001b[0m: \u001b[3;91mFalse\u001b[0m\n",
"\u001b[1m}\u001b[0m\n"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# Fishers exact test\n",
"pprint(rTZ[\"global_tests\"][\"fisher\"], expand_all=True)"
]
},
{
"cell_type": "markdown",
"id": "c1076374-3f45-47b6-961b-7d5f6897ff80",
"metadata": {},
"source": [
"### Conclusion"
]
},
{
"cell_type": "markdown",
"id": "089bf384",
"metadata": {},
"source": [
"- Both tests have p-values larger than $0.05$ (chi-square: $p = 0.569$, Fisher: $p = 0.487$), so `reject_alpha: False` means you **do not reject** the null hypothesis $H_0$ at significance level $\\alpha = 0.05$.\n",
"\n",
"- Here $H_0$ is **independence** of $T$ and $Z$, i.e. for $z \\in \\{0,1\\}$:\n",
" $$\n",
" P(T \\mid Z=z) = P(T).\n",
" $$\n",
" So your conclusion is: **you do not have statistically significant evidence that $T$ depends on $Z$** (you cannot claim $P(T\\mid Z)$ differs from $P(T)$ based on this sample).\n",
"\n",
"- Also, one expected count is very small (about $0.603$), so the chi-square approximation may be unreliable; **Fisher’s exact test** is the safer one here, and it is also not significant."
]
},
{
"cell_type": "markdown",
"id": "6b46ab90",
"metadata": {},
"source": [
"## Prentice Criteria (PC) evaluation framework\n",
"\n",
"It was by Google AI. In practice, these are tested using a nested series of regression models:\n",
"\n",
"1. **Model for PC 1 (Effect of $Z$):**\n",
"\n",
"$$\n",
" \\operatorname{logit}(P(T=1)) = \\mu_1 + \\beta Z\n",
"$$ \n",
"\n",
"*Requirement:* $\\beta \\neq 0$\n",
"\n",
"3. **Model for PC 2 (Effect of $Z$ on $S$):**\n",
"\n",
"$$\n",
" E[S] = \\mu_2 + \\alpha Z\n",
"$$ \n",
"\n",
"*Requirement:* $\\alpha \\neq 0$\n",
"\n",
"5. **Model for PC 3 (The Full Model):**\n",
"\n",
"$$\n",
" \\operatorname{logit}(P(T=1)) = \\mu_3 + \\gamma S + \\beta_S Z\n",
"$$\n",
"\n",
"*Requirement (Criterion 4):* $\\gamma \\neq 0$ and $\\beta_S \\to 0$\n",
"\n",
"**Note:** PC 4 is notoriously difficult to satisfy perfectly. Researchers often calculate the **Proportion Explained (PE)**:\n",
"$$\n",
" PE = \\frac{\\beta - \\beta_S}{\\beta}\n",
"$$"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "2242fb0d",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"--- Prentice Criteria Evaluation ---\n",
"\n",
"1. Treatment effect on T: p = 0.5752 (Fail)\n",
"2. Treatment effect on S: p = 0.9909 (Fail)\n",
"3. Surrogate effect on T: p = 0.0041 (Pass)\n",
"4. Full Mediation (Z effect given S): p = 0.6442\n",
" RESULT: Pass (Treatment effect is fully captured by Surrogate)\n",
"\n",
"Proportion of Treatment Effect Explained (PE): -53.90%\n"
]
}
],
"source": [
"import statsmodels.api as sm\n",
"import statsmodels.formula.api as smf\n",
"\n",
"df = df_work.copy()\n",
"\n",
"print(\"--- Prentice Criteria Evaluation ---\\n\")\n",
"\n",
"# Criterion 1: Treatment effect on True Endpoint (T ~ Z)\n",
"model1 = smf.logit(\"T ~ Z\", data=df).fit(disp=0)\n",
"p1 = model1.pvalues['Z']\n",
"print(f\"1. Treatment effect on T: p = {p1:.4f} ({'Pass' if p1 < 0.05 else 'Fail'})\")\n",
"\n",
"# Criterion 2: Treatment effect on Surrogate (S ~ Z)\n",
"model2 = smf.ols(\"S ~ Z\", data=df).fit()\n",
"p2 = model2.pvalues['Z']\n",
"print(f\"2. Treatment effect on S: p = {p2:.4f} ({'Pass' if p2 < 0.05 else 'Fail'})\")\n",
"\n",
"# Criterion 3: Surrogate effect on True Endpoint (T ~ S)\n",
"model3 = smf.logit(\"T ~ S\", data=df).fit(disp=0)\n",
"p3 = model3.pvalues['S']\n",
"print(f\"3. Surrogate effect on T: p = {p3:.4f} ({'Pass' if p3 < 0.05 else 'Fail'})\")\n",
"\n",
"# Criterion 4: Full Mediation (T ~ S + Z)\n",
"# The treatment effect (Z) should become non-significant when S is included\n",
"model4 = smf.logit(\"T ~ S + Z\", data=df).fit(disp=0)\n",
"p4_z = model4.pvalues['Z']\n",
"p4_s = model4.pvalues['S']\n",
"\n",
"print(f\"4. Full Mediation (Z effect given S): p = {p4_z:.4f}\")\n",
"if p4_z > 0.05 and p4_s < 0.05:\n",
" print(\" RESULT: Pass (Treatment effect is fully captured by Surrogate)\")\n",
"else:\n",
" print(\" RESULT: Fail (Significant direct treatment effect remains)\")\n",
"\n",
"# Calculate Proportion Explained (PE)\n",
"beta_unadj = model1.params['Z']\n",
"beta_adj = model4.params['Z']\n",
"pe = (beta_unadj - beta_adj) / beta_unadj\n",
"print(f\"\\nProportion of Treatment Effect Explained (PE): {pe:.2%}\")\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "30841dae",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"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.10.12"
}
},
"nbformat": 4,
"nbformat_minor": 5
}