BioStatistik/2x2-tabel.ipynb

295 lines
10 KiB
Plaintext

{
"cells": [
{
"cell_type": "code",
"execution_count": 2,
"id": "bac57c6e-48a0-4414-bf65-ed4ff751aa87",
"metadata": {},
"outputs": [],
"source": [
"# Imports\n",
"\n",
"from IPython.display import display, Markdown\n",
"from scipy.stats import chi2_contingency\n",
"from scipy.stats import t as t_test\n",
"import numpy as np\n",
"t_value = t_test.isf\n",
"\n",
"def _display_table(data_array, row_names=None, col_names=None):\n",
" _row_num = len(data_array)\n",
" _col_num = len(data_array[0])\n",
" _rows = []\n",
" for i in range(_row_num):\n",
" row = f'| {row_names[i]} |'\n",
" for j in range(_col_num):\n",
" row += f' {data_array[i][j]:.1f} |'\n",
" row += f' {sum(data_array[i]):.0f} |'\n",
" _rows.append(row)\n",
" _total_row = '| **Total** |'\n",
" _col_tots = 0\n",
" for i in range(_col_num):\n",
" col_tot = 0\n",
" for j in range(_row_num):\n",
" col_tot += data_array[j][i]\n",
" _col_tots += col_tot\n",
" _total_row += f' **{col_tot:.0f}** |'\n",
" _total_row += f' **{_col_tots:.0f}** |'\n",
" display(Markdown(\n",
" rf\"\"\"\n",
"| | {' | '.join(col_names + ['Total'])} |\n",
"{'|-'*(len(row_names) + 2)} |\n",
"{'\\n'.join(_rows)}\n",
"{_total_row}\n",
"\"\"\"\n",
"))\n",
"\n"
]
},
{
"cell_type": "markdown",
"id": "1616dacd-4132-46dd-a1a0-df813b634b12",
"metadata": {},
"source": [
"# Sensitivitet, specificitet og positiv/negativ prædiktiv værdi"
]
},
{
"cell_type": "markdown",
"id": "ad5c44e5-dc99-4665-a1c2-1b9b1586a175",
"metadata": {},
"source": [
"$$\n",
"Sensitivitet = P(Positiv\\ test | syg) = \\frac{antal\\ sandt\\ positive}{antal\\ sandt\\ positive + antal\\ falsk\\ negative}\n",
"$$\n",
"\n",
"$$\n",
"Specificitet = P(Negativ\\ test|rask) = \\frac{antal\\ sandt\\ negative}{antal\\ sandt\\ negative + antal\\ falsk\\ positive}\n",
"$$\n",
"\n",
"$$\n",
"PPV = P(Syg|positiv\\ test) = \\frac{antal\\ sande\\ positive}{antal\\ sande\\ positive + antal\\ falske\\ positive}\n",
"$$\n",
"\n",
"$$\n",
"NPV = P(Rask|negativ\\ test) = \\frac{antal\\ sande\\ negative}{antal\\ sande\\ negative + antal\\ falske\\ negative}\n",
"$$"
]
},
{
"cell_type": "markdown",
"id": "c220e249-002a-4536-8e87-424acb2e8190",
"metadata": {},
"source": [
"## Tabel ud fra positive og negative\n",
"\n",
"| | Syg | Ikke syg | I alt |\n",
"| :----------- | :--------------: | :--------------: | --------------------------------: |\n",
"| Test positiv | _sandt positive_ | _falsk positive_ | Total positive |\n",
"| Test negativ | _falsk negative_ | _sandt negative_ | Total negative |\n",
"| I alt | Total syge | Total raske | **n** |"
]
},
{
"cell_type": "code",
"execution_count": 19,
"id": "af36924c-e2e7-46cf-9bde-5a94b9d427e3",
"metadata": {},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"### 2x2-tabel\n",
"\n",
"| | Syg | Ikke syg | I alt |\n",
"| :----------- | :--------------: | :--------------: | --------------------------------: |\n",
"| Test positiv | 117 | 796 | 913 |\n",
"| Test negativ | 20 | 3142 | 3162 |\n",
"| I alt | 137 | 3938 | **4075** |\n",
"\n",
"<span style='color:red'>Sensitivitet =</span> $\\frac{sandt\\ positive}{sandt\\ positive + falsk\\ negative} = \\frac{117}{117 + 20} \\approx$ 85.40%\n",
"\n",
"<span style='color:blue'>Specificitet =</span> $\\frac{sandt\\ negative}{sandt\\ negative + falsk\\ positive} = \\frac{3142}{3142 + 796} \\approx$ 79.79%\n",
"\n",
"For personer, der er syge, vil testen altså 85.40% af tiden vise positiv.\n",
"\n",
"Ligeledes vil testen for personer, der ikke er syge, vise negativ 79.79% af tiden.\n",
"\n",
"### PPV og NPV\n",
"\n",
"<span style='color:red'>PPV =</span> $\\frac{sandt\\ positive}{sandt\\ positive + falsk\\ positive} = \\frac{117}{117 + 796} \\approx$ 12.81%\n",
"\n",
"<span style='color:blue'>NPV =</span> $\\frac{sandt\\ negative}{sandt\\ negative + falsk\\ negative} = \\frac{3142}{3142 + 20} \\approx$ 99.37%\n",
"\n",
"For en person, der tester positiv, vil der være en 12.81% sandsynlighed for, at de reelt er syge.\n",
"\n",
"For en person, der tester negativ, vil der være en 99.37% sandsynlighed for, at de reelt er raske.\n"
],
"text/plain": [
"<IPython.core.display.Markdown object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"sandt_positive = 117\n",
"sandt_negative = 3142\n",
"\n",
"falsk_positive = 796\n",
"falsk_negative = 20\n",
"\n",
"\n",
"############################################\n",
"sensitivitet = sandt_positive / (sandt_positive + falsk_negative)\n",
"specificitet = sandt_negative / (sandt_negative + falsk_positive)\n",
"ppv = sandt_positive / (sandt_positive + falsk_positive)\n",
"npv = sandt_negative / (sandt_negative + falsk_negative)\n",
"\n",
"sum_syge = sandt_positive + falsk_negative\n",
"sum_ikke_syge = falsk_positive + sandt_negative\n",
"sum_positive = sandt_positive + falsk_positive\n",
"sum_negative = sandt_negative + falsk_negative\n",
"\n",
"display(Markdown(\n",
" rf\"\"\"\n",
"### 2x2-tabel\n",
" \n",
"| | Syg | Ikke syg | I alt |\n",
"| :----------- | :--------------: | :--------------: | --------------------------------: |\n",
"| Test positiv | {sandt_positive} | {falsk_positive} | {sum_positive} |\n",
"| Test negativ | {falsk_negative} | {sandt_negative} | {sum_negative} |\n",
"| I alt | {sum_syge} | {sum_ikke_syge} | **{sum_positive + sum_negative}** |\n",
"\n",
"<span style='color:red'>Sensitivitet =</span> $\\frac{{sandt\\ positive}}{{sandt\\ positive + falsk\\ negative}} = \\frac{{{sandt_positive}}}{{{sandt_positive} + {falsk_negative}}} \\approx$ {sensitivitet:.2%}\n",
"\n",
"<span style='color:blue'>Specificitet =</span> $\\frac{{sandt\\ negative}}{{sandt\\ negative + falsk\\ positive}} = \\frac{{{sandt_negative}}}{{{sandt_negative} + {falsk_positive}}} \\approx$ {specificitet:.2%}\n",
"\n",
"For personer, der er syge, vil testen altså {sensitivitet:.2%} af tiden vise positiv.\n",
"\n",
"Ligeledes vil testen for personer, der ikke er syge, vise negativ {specificitet:.2%} af tiden.\n",
"\n",
"### PPV og NPV\n",
"\n",
"<span style='color:red'>PPV =</span> $\\frac{{sandt\\ positive}}{{sandt\\ positive + falsk\\ positive}} = \\frac{{{sandt_positive}}}{{{sandt_positive} + {falsk_positive}}} \\approx$ {ppv:.2%}\n",
"\n",
"<span style='color:blue'>NPV =</span> $\\frac{{sandt\\ negative}}{{sandt\\ negative + falsk\\ negative}} = \\frac{{{sandt_negative}}}{{{sandt_negative} + {falsk_negative}}} \\approx$ {npv:.2%}\n",
"\n",
"For en person, der tester positiv, vil der være en {ppv:.2%} sandsynlighed for, at de reelt er syge.\n",
"\n",
"For en person, der tester negativ, vil der være en {npv:.2%} sandsynlighed for, at de reelt er raske.\n",
"\"\"\"\n",
"))"
]
},
{
"cell_type": "markdown",
"id": "d72087c9-96b0-4584-bae2-854068fb9de5",
"metadata": {},
"source": [
"## PPV ud fra sensitivitet, specificitet og prævalens"
]
},
{
"cell_type": "markdown",
"id": "833a7a8d-f012-4a0f-b39d-fc1ae3d8a1b1",
"metadata": {},
"source": [
"$$\n",
"PPV = \\frac{sensitivitet \\cdot prævalens}{sensitivitet \\cdot prævalens + (1-specificitet) \\cdot (1-prævalens)}\n",
"$$"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "0b81b6b9-268a-4338-bff9-d5a7c1636a67",
"metadata": {},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"$\n",
"PPV = \\frac{sensitivitet \\cdot prævalens}{sensitivitet \\cdot prævalens + (1-specificitet) \\cdot (1-prævalens)}\n",
"$\n",
"\n",
"$\n",
"= \\frac{0.854 \\cdot 0.05}{0.854 \\cdot 0.05 + (1-0.798) \\cdot (1-0.05)}\n",
"$\n",
"\n",
"$\n",
"= 18.20%\n",
"\\%\n",
"$\n",
"\n",
"Altså vil der være en sandsynlighed på 18.20% for, at en person faktisk er syg, hvis testen er positiv.\n"
],
"text/plain": [
"<IPython.core.display.Markdown object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"sensitivitet = 0.854\n",
"specificitet = 0.798\n",
"prævalens = 0.05\n",
"\n",
"ppv = sensitivitet * prævalens / (sensitivitet * prævalens + (1-specificitet) * (1-prævalens))\n",
"\n",
"display(Markdown(\n",
" rf\"\"\"\n",
"$\n",
"PPV = \\frac{{sensitivitet \\cdot prævalens}}{{sensitivitet \\cdot prævalens + (1-specificitet) \\cdot (1-prævalens)}}\n",
"$\n",
"\n",
"$\n",
"= \\frac{{{sensitivitet} \\cdot {prævalens}}}{{{sensitivitet} \\cdot {prævalens} + (1-{specificitet}) \\cdot (1-{prævalens})}}\n",
"$\n",
"\n",
"$\n",
"= {ppv:.2%}\n",
"\\%\n",
"$\n",
"\n",
"Altså vil der være en sandsynlighed på {ppv:.2%} for, at en person faktisk er syg, hvis testen er positiv.\n",
"\"\"\"\n",
"))"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b6fab8ba-02cc-478d-b3f0-32d55c6400c8",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "base",
"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.9"
}
},
"nbformat": 4,
"nbformat_minor": 5
}