Skip to content

Instantly share code, notes, and snippets.

@tdsmith
Created July 18, 2018 05:35
Show Gist options
  • Save tdsmith/e27ee1d8f9f09e97c9a7cb973f5b8380 to your computer and use it in GitHub Desktop.
Save tdsmith/e27ee1d8f9f09e97c9a7cb973f5b8380 to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Empirical power analysis\n",
"\n",
"tdsmith@mozilla.com, 2018-07-17\n",
"\n",
"This notebook demonstrates how to run an empirical power analysis on data from a Poisson distribution, which is intended to approximate the distribution of indices of search bar results chosen by Firefox users."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"%matplotlib inline\n",
"from IPython.display import display\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"import pandas as pd\n",
"import scipy.stats as stats"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Generate a parent distribution that we'll sample from iteratively.\n",
"\n",
"For a real analysis, the parent distribution should be a large sample of the actual observed telemetry data.\n",
"\n",
"$\\mu$ is the location parameter and arithmetic mean of the Poisson distribution."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[1 3 1 2 0 0 2 1 0 4]\n"
]
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"parent = stats.poisson.rvs(mu=1, size=int(1e6))\n",
"\n",
"# show that the Poisson distribution yields integers\n",
"print(parent[:10])\n",
"\n",
"fig, ax = plt.subplots()\n",
"ax.hist(parent, bins=np.arange(parent.max() + 2), align=\"left\")\n",
"None"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Sanity check: if we take two independent samples from our parent distribution, we should call a difference about 5% of the time at p=0.05."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.0506"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"n_iterations = 5000\n",
"n_samples = 1000\n",
"n_positive = 0\n",
"p = 0.05\n",
"\n",
"for _ in range(n_iterations):\n",
" # Sampling with replacement is the default, but let's be explicit.\n",
" a = np.random.choice(parent, n_samples, replace=True)\n",
" b = np.random.choice(parent, n_samples, replace=True)\n",
" _u, test_p = stats.mannwhitneyu(a, b)\n",
" # multiply by 2 for a 2-sided alternative hypothesis\n",
" if test_p*2 < p:\n",
" n_positive += 1\n",
"\n",
"n_positive / n_iterations"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"That's close enough for government work.\n",
"\n",
"## Power analysis\n",
"\n",
"Our empirical power analysis will tell us how often we call a statistically significant difference between two samples, which we'll call $a$ and $b$, each of size $N$, when there is a true difference $\\frac{\\textrm{mean}(\\textrm{parent}_b)}{\\textrm{mean}(\\textrm{parent}_a)} = 1+\\Delta$ in the means of the respective parent distributions of the samples.\n",
"\n",
"Customarily, we want to choose $N$ so that we call a difference at least $(1-\\beta) = 80\\%$ of the time.\n",
"\n",
"To do this, we will sweep over a range of values for $N$. At each $N$, we will repeat many times the process of drawing samples $a$ and $b$ and performing a U test, counting the number of times our test reports $p < \\alpha$. The fraction of iterations that yield a significant value will be our power.\n",
"\n",
"---\n",
"\n",
"Concretely, we'll let `a` be a sample from `parent` at each iteration. How do we generate a sample `b`?\n",
"\n",
"There are at least a couple of options; they both seem reasonable to me:\n",
"\n",
"* If the parent distribution is adequately modeled by a parametric distribution, choose `b` from a parametric distribution with parameters reflecting your model of the intervention.\n",
"* Take `b` as an independent sample from `parent` and manipulate it under a model of the effect you expect (or fear) your intervention will have.\n",
"\n",
"I'll pursue the latter here since it's a little more interesting to write.\n",
"\n",
"I'll use a model suggesting that the effect of a bad frecency guess is generally small and distributed over the sample.\n",
"\n",
"A simple model is to choose $\\Delta \\cdot \\textrm{mean(parent)} \\cdot N$ values from the sample with replacement and increment them by 1. This will increase the mean of the sample by a factor of about $1+\\Delta$."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"parent_mean = parent.mean()\n",
"delta = 0.05\n",
"\n",
"def test_sample(n_samples):\n",
" a = np.random.choice(parent, n_samples, replace=True)\n",
" b = np.random.choice(parent, n_samples, replace=True)\n",
" n_to_frob = int(np.round(parent_mean*delta*n_samples))\n",
" to_frob = np.random.randint(low=0, high=n_samples, size=n_to_frob)\n",
" for i in to_frob:\n",
" b[i] += 1\n",
" return {\n",
" \"a_mean\": a.mean(),\n",
" \"b_mean\": b.mean(),\n",
" \"p\": stats.mannwhitneyu(a, b)[1]\n",
" }"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's try the function out on a small sample and run it for a bunch of iterations."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"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>a_mean</th>\n",
" <th>b_mean</th>\n",
" <th>p</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>1.023</td>\n",
" <td>1.109</td>\n",
" <td>0.034640</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>1.004</td>\n",
" <td>1.010</td>\n",
" <td>0.382725</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>1.036</td>\n",
" <td>1.043</td>\n",
" <td>0.246348</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>0.983</td>\n",
" <td>1.026</td>\n",
" <td>0.240245</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>0.983</td>\n",
" <td>1.054</td>\n",
" <td>0.083785</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" a_mean b_mean p\n",
"0 1.023 1.109 0.034640\n",
"1 1.004 1.010 0.382725\n",
"2 1.036 1.043 0.246348\n",
"3 0.983 1.026 0.240245\n",
"4 0.983 1.054 0.083785"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"0.282"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"n_samples = 1000\n",
"n_iterations = 1000\n",
"alpha = 0.05\n",
"\n",
"rows = [test_sample(n_samples) for _ in range(n_iterations)]\n",
"results = pd.DataFrame(rows)\n",
"display(results.head())\n",
"\n",
"power = (results[\"p\"] < alpha).sum() / len(results)\n",
"power"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"It looks like our observed power's in the neighborhood of 30%, which is less than the 80% we'd like to obtain.\n",
"\n",
"Let's try sweeping over a range of values for N and plotting the result."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"N_grid = [int(i) for i in [1e3, 3e3, 1e4, 3e4]]\n",
"partial_results = []\n",
"\n",
"for n_samples in N_grid:\n",
" rows = [test_sample(n_samples) for _ in range(n_iterations)]\n",
" partial_results.append(pd.DataFrame(rows).assign(N=n_samples))\n",
"results = pd.concat(partial_results)\n",
"results[\"significant\"] = results[\"p\"] < alpha\n",
"\n",
"power = (\n",
" results\n",
" .groupby(\"N\")\n",
" [\"significant\"]\n",
" .sum()\n",
" / n_iterations\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Text(0,0.5,'Power for delta=0.05, p=0.05')"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"fig, ax = plt.subplots()\n",
"ax.semilogx(power.index, power.values, \"o-\")\n",
"ax.set_ylim(0, 1.1)\n",
"ax.set_xlabel(\"Number of samples in each leg\")\n",
"ax.set_ylabel(f\"Power for delta={delta}, p={p}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In this model, around 10,000 samples in each leg looks like enough to detect a one-sided difference of 5% in the mean with high confidence.\n",
"\n",
"But we should make sure we're running enough iterations at each N to get a reliable answer. To build confidence, you can repeat the analysis for a given number of iterations at each N many times, and plot the average and some measure of spread of the observed powers in order to convince yourself that you're getting reliable results."
]
}
],
"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.6.4"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
appnope==0.1.0
backcall==0.1.0
bleach==2.1.3
cycler==0.10.0
decorator==4.3.0
entrypoints==0.2.3
html5lib==1.0.1
ipykernel==4.8.2
ipython==6.4.0
ipython-genutils==0.2.0
ipywidgets==7.3.0
jedi==0.12.1
Jinja2==2.10
jsonschema==2.6.0
jupyter==1.0.0
jupyter-client==5.2.3
jupyter-console==5.2.0
jupyter-core==4.4.0
kiwisolver==1.0.1
MarkupSafe==1.0
matplotlib==2.2.2
mistune==0.8.3
nbconvert==5.3.1
nbformat==4.4.0
notebook==5.6.0
numpy==1.14.5
pandas==0.23.3
pandocfilters==1.4.2
parso==0.3.1
pexpect==4.6.0
pickleshare==0.7.4
prometheus-client==0.3.0
prompt-toolkit==1.0.15
ptyprocess==0.6.0
Pygments==2.2.0
pyparsing==2.2.0
python-dateutil==2.7.3
pytz==2018.5
pyzmq==17.1.0
qtconsole==4.3.1
scipy==1.1.0
seaborn==0.9.0
Send2Trash==1.5.0
simplegeneric==0.8.1
six==1.11.0
terminado==0.8.1
testpath==0.3.1
tornado==5.1
traitlets==4.3.2
wcwidth==0.1.7
webencodings==0.5.1
widgetsnbextension==3.3.0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment