Chance, Bias and Confounding: Why an Association Is Not Yet a Treatment Effect

Health EconomicsClinical Epidemiology ResearchMethodology and Research Design
Chance, Bias and Confounding: Why an Association Is Not Yet a Treatment Effect
On this page

อ่านฉบับภาษาไทย (Thai version)

Abstract

A district hospital committee must decide whether to pay for C, a new preventive treatment. Two studies sit on its desk. In a small trial, 12.12% of patients on C and 21.67% on usual care, A, had a serious complication within a year: a risk ratio of 0.56 (95% confidence interval 0.25 to 1.26). The provincial hospital's records of 1,000 patients say the opposite: 24.6% against 11.2%, a ratio of 2.20. We test three explanations in turn. Chance explains the trial's wide interval, and more patients would shrink it. Confounding explains the records: doctors gave C mostly to patients with severe disease. Comparing the same patients, by averaging within severity groups or by weighting each patient, gives 16.5% against 22.0%, a ratio of 0.75. Bias from how complications were recorded or when follow-up started does not shrink with more patients. The committee's economic model needs one input from this: 5.5 complications avoided per 100 patients.


Visual summary · ภาพสรุป

Two studies, two answers on the committee's desk

A district hospital committee must decide whether to pay for C, a new preventive treatment for adults newly diagnosed with a chronic condition. In a trial, 8 of 66 patients given C and 13 of 60 given usual care, A, had a serious complication within one year. These are illustrative numbers for teaching, not results of a real study.

The provincial hospital has also sent its records, with illustrative numbers too. In recent years, 500 of its patients received C and 500 received A. Within one year, 123 on C and 56 on A had a serious complication. The records hold about eight times as many patients as the trial.

The two studies disagree. Dividing the risk on C by the risk on A gives a risk ratio, where 1 means no difference (Risk Ratio, Odds Ratio, Risk Difference and NNT: One 2×2 Table, Four Answers). It is 0.56 in the trial, so fewer complications on C, but 2.20 in the records, more than twice as many. One member trusts the records because they are bigger; another trusts the trial because its patients were randomly assigned, so nothing about them decided who received C.

Before either number can stand for what C does, three other explanations have to be ruled out. Chance: the patients who happened to be studied differ from the next ones. Bias: the study measured or counted patients in a skewed way. Confounding: the patients on C differed from those on A before treatment began.

This article takes them one at a time with these two studies. It ends with the number the economic model needs.

Chance: another sample, another number

Read first on this site:

Chance is the error that comes from which patients happened to be studied: another 66 and 60 patients from the same district would give slightly different counts and a different ratio. The smaller the study, the bigger this wobble.

A 95% confidence interval shows how big the wobble is: it is the range of true effects the data cannot rule out. The risk-ratio article builds the trial's interval step by step (Risk Ratio, Odds Ratio, Risk Difference and NNT: One 2×2 Table, Four Answers). Risks of 12.12% on C and 21.67% on A give a risk ratio of 0.56 and 9.55 fewer complications per 100 patients, with an interval for the ratio from 0.25 to 1.26.

That interval runs from a large benefit to some harm, so the trial cannot rule out that C does nothing. Nor does it show that C does nothing: the trial is too small to tell.

The size of the wobble is one number, called the spread. It is built only from the four counts: the fewer patients had a complication, the larger it is, and here only 8 and 13 did. The worked example computes it and shows what more patients would change.

What more patients would do to the trial's interval

Every step can be checked with a calculator from the numbers shown in it. ln is the natural logarithm, and raising e to a power undoes it.

  1. The spread from the four counts

    \[ \sqrt{\tfrac{1}{8}-\tfrac{1}{66}+\tfrac{1}{13}-\tfrac{1}{60}}=0.412 \]

    This is the typical size of the chance error in the log of the risk ratio. The terms for 8 and 13 are the largest, because so few patients had a complication.

  2. The trial's interval

    \[ e^{\ln 0.56\,\pm\,1.96\times 0.412}=0.25,\ 1.26 \]

    Move 1.96 spreads down and up from ln 0.56, then undo the log with e: from 0.25 to 1.26. The 1.96 makes it a 95% interval: it covers the middle 95% of chance errors.

  3. Ten times the patients, the same risks

    \[ \sqrt{\tfrac{1}{80}-\tfrac{1}{660}+\tfrac{1}{130}-\tfrac{1}{600}}=0.130 \]

    With 80 of 660 patients on C and 130 of 600 on A having a complication, every term is ten times smaller. The spread falls to about a third.

  4. The narrower interval

    \[ e^{\ln 0.56\,\pm\,1.96\times 0.130}=0.43,\ 0.72 \]

    The interval now runs from 0.43 to 0.72. It no longer includes 1, so chance alone becomes an unlikely explanation for the benefit.

Result: More patients shrink chance: ten times the patients leave about a third of the spread around the same 0.56.

A narrow interval is not a right answer

The records have the opposite problem. With 123 and 56 patients with a complication, their counts are large, and the interval around 2.20 is narrow: 1.64 to 2.94. It does not even touch the trial's interval, which ends at 1.26. Chance is therefore an unlikely explanation for why the two studies disagree.

A narrow interval says a number is precise. It does not say the number is right: 1,000 patients compared unfairly give a precise wrong answer.

Chance also grows with the number of questions asked. A 95% interval misses the true value in 5 of every 100 studies, by design. If the trial had checked 20 independent outcomes that C does not change at all, the chance that at least one interval excludes 1 by luck alone would be $1-0.95^{20}=64.2\%$. One striking result among many deserves suspicion.

R code chance.R
# Writes: stdout only. The illustrative trial: serious complications within one year on C and on A.
risk_c <- 8 / 66
risk_a <- 13 / 60
spread <- sqrt(1 / 8 - 1 / 66 + 1 / 13 - 1 / 60)
spread10 <- sqrt(1 / 80 - 1 / 660 + 1 / 130 - 1 / 600)
f <- function(x, d) formatC(x, d, format = "f")
limits <- function(s) f(exp(log(risk_c / risk_a) + c(-1.96, 1.96) * s), 2)
cat("Risk on C:", f(100 * risk_c, 2), "%  on A:", f(100 * risk_a, 2), "%\n")
cat("Risk ratio:", f(risk_c / risk_a, 2), "  95% interval:", limits(spread), "\n")
cat("Complications avoided per 100 patients:", f(100 * (risk_a - risk_c), 2), "\n")
cat("Spread from the four counts:", f(spread, 3), "\n")
cat("Ten times the patients: spread", f(spread10, 3), "  95% interval:", limits(spread10), "\n")
cat("Chance that at least 1 of 20 intervals misses:", f(100 * (1 - 0.95^20), 1), "%\n")
Output of the run chance.log
Risk on C: 12.12 %  on A: 21.67 %
Risk ratio: 0.56   95% interval: 0.25 1.26
Complications avoided per 100 patients: 9.55
Spread from the four counts: 0.412
Ten times the patients: spread 0.130   95% interval: 0.43 0.72
Chance that at least 1 of 20 intervals misses: 64.2 %
The trial, traced: its two risks, the risk ratio and its interval, the complications avoided per 100 patients, the spread for the real trial and for one ten times bigger, and the chance of a false alarm among 20 outcomes.

Confounding: severity decides who gets C

If chance cannot explain the records, what turned C's benefit into harm? The hospital's doctors did not toss a coin. They gave C mostly to patients whose disease was severe at diagnosis: 400 of the 500 patients on C were severe, but only 100 of the 500 on A.

Severity also drives the outcome. On A, 40 of the 100 severe patients had a serious complication within a year, against 16 of the 400 mild ones: 40.0% against 4.0%. So the C group starts out with far more patients who were likely to have a complication whatever they received.

The fair comparison is inside each severity group, where patients on C and on A started out alike. The worked example compares them group by group and then pools them again.

Compare like with like, then pool

Each step divides the share with a complication on C by the share on A.

  1. Severe patients

    \[ \frac{120/400}{40/100}=\frac{30.0}{40.0}=0.75 \]

    Among severe patients, 30.0% had a complication on C and 40.0% on A. C lowers the risk by a quarter.

  2. Mild patients

    \[ \frac{3/100}{16/400}=\frac{3.0}{4.0}=0.75 \]

    Among mild patients, 3.0% on C against 4.0% on A: the same ratio.

  3. Pool both groups

    \[ \frac{123/500}{56/500}=\frac{24.6}{11.2}=2.20 \]

    Counting severe and mild patients together gives 24.6% on C against 11.2% on A. The ratio flips to 2.20, or 13.4 extra complications per 100 patients on C.

  4. Why it flips

    \[ \frac{400}{500}=80\%,\quad \frac{100}{500}=20\% \]

    Four in five patients on C were severe, against one in five on A. The pooled C group is mostly high-risk patients, so its risk is high even though C helps in each group.

Result: C lowers the risk by a quarter in each severity group, yet looks harmful when the groups are pooled. The pooled 2.20 mostly measures who received C, not what C does.

Name it, then draw it

Read first on this site:

A factor that affects both who receives a treatment and the outcome is called a confounder, and the distortion it causes is confounding [1]. When the factor is the very reason for prescribing, as severity is here, it is called confounding by indication. It can also run the other way, called confounding by contraindication: doctors may hold a drug back from frail patients, which makes the drug look better than it is.

Figure 1 draws the records' causes as arrows we assume from clinical knowledge: severity leads to C, severity leads to complications, and C may lead to fewer complications. Because no arrow loops back, such a drawing is called a directed acyclic graph, or DAG.

Figure 1. Follow the two orange arrows leaving severity: it sent 80% of severe but only 20% of mild patients to C, and it raises the risk on A from 4.0% to 40.0%. That shared cause is why the pooled ratio of 2.20 mixes severity's effect with C's own 0.75 on the blue arrow.
R code risks.R
# Writes: stdout only. Illustrative hospital records: serious complications within one year.
complications_c <- c(severe = 120, mild = 3); patients_c <- c(severe = 400, mild = 100)
complications_a <- c(severe = 40, mild = 16); patients_a <- c(severe = 100, mild = 400)
risk_c <- c(complications_c / patients_c, all = sum(complications_c) / sum(patients_c))
risk_a <- c(complications_a / patients_a, all = sum(complications_a) / sum(patients_a))
ratio <- risk_c / risk_a
spread <- sqrt(1 / 123 - 1 / 500 + 1 / 56 - 1 / 500)
f <- function(x, d) formatC(x, d, format = "f")
cat("Risk on C, severe / mild / all:", f(100 * risk_c, 1), "%\n")
cat("Risk on A, severe / mild / all:", f(100 * risk_a, 1), "%\n")
cat("Risk ratio, severe / mild / all:", f(ratio, 2), "\n")
cat("All patients, 95% interval:", f(exp(log(ratio[["all"]]) + c(-1.96, 1.96) * spread), 2), "\n")
cat("Extra complications per 100 on C, all:", f(100 * (risk_c[["all"]] - risk_a[["all"]]), 1), "\n")
Output of the run risks.log
Risk on C, severe / mild / all: 30.0 3.0 24.6 %
Risk on A, severe / mild / all: 40.0 4.0 11.2 %
Risk ratio, severe / mild / all: 0.75 0.75 2.20
All patients, 95% interval: 1.64 2.94
Extra complications per 100 on C, all: 13.4
The records, traced: the risk on C and on A among severe patients, mild patients and all patients, the three risk ratios, the interval around the pooled ratio, and the extra complications per 100 patients that pooling suggests.

Standardization: give both treatments to the same patients

Read first on this site:

The committee needs one number for the whole district, not one per severity group, and certainly not the pooled 2.20. The fix is to ask both treatments the same question: what would the risk be if the same patients all received C, and if they all received A?

Take the records' own patients: 500 severe patients and 500 mild ones, half and half. If all of them received C, half would carry the severe risk of 30.0% and half the mild risk of 3.0%: $0.5\times30.0+0.5\times3.0=16.5\%$. If all received A: $0.5\times40.0+0.5\times4.0=22.0\%$. Both risks now describe the same patients.

Their ratio is 16.5 / 22.0 = 0.75, the same as inside each severity group, and the difference is 5.5 complications avoided per 100 patients. Averaging over one chosen mix of patients like this is called standardization [2]. In symbols, $R_C=\sum_s w_s R_{C,s}$, where $w_s$ is the share of patients in severity group $s$ and $R_{C,s}$ the risk on C in that group.

The chosen mix matters. Here C lowers the risk by a quarter in both groups, so any mix gives 0.75, but the number of complications avoided depends on how many patients are severe. The model should use the district's own mix of patients.

Standardization fixes where the estimate sits; its interval still describes only chance. Each of the four group risks has its own chance error, and combining them with the same half-and-half shares gives a spread of 0.143 for the log of the ratio. As before, $e^{\ln 0.75\pm1.96\times0.143}$ runs from 0.57 to 0.99. Figure 2 puts the trial, the pooled records and the standardized records side by side.

Figure 2. Compare the orange line, the pooled records, with the grey band, the trial's interval: they do not overlap, so chance is an unlikely explanation for the gap. The blue line, the same records with both treatments given to the same patients, sits inside the band, so once severity is handled the records and the trial agree. The dashed line at 1 means no difference.
R code standardize.R
# Writes: stdout only. Both treatments given to the same patients: the records' mix, half severe.
share <- c(severe = 0.5, mild = 0.5)
risk_c <- c(120 / 400, 3 / 100); patients_c <- c(400, 100)
risk_a <- c(40 / 100, 16 / 400); patients_a <- c(100, 400)
std_c <- sum(share * risk_c); std_a <- sum(share * risk_a)
spread <- sqrt(sum(share^2 * risk_c * (1 - risk_c) / patients_c) / std_c^2 +
               sum(share^2 * risk_a * (1 - risk_a) / patients_a) / std_a^2)
limits <- exp(log(std_c / std_a) + c(-1.96, 1.96) * spread); avoided <- 100 * std_a * (1 - limits)
f <- function(x, d) formatC(x, d, format = "f")
cat("Standardized risk on C:", f(100 * std_c, 1), "%  on A:", f(100 * std_a, 1), "%\n")
cat("Risk ratio:", f(std_c / std_a, 2), "  spread of its log:", f(spread, 3), "\n")
cat("95% interval:", f(limits, 2), "\n")
cat("Avoided per 100:", f(100 * (std_a - std_c), 1), "  at the limits:", f(avoided, 1), "\n")
Output of the run standardize.log
Standardized risk on C: 16.5 %  on A: 22.0 %
Risk ratio: 0.75   spread of its log: 0.143
95% interval: 0.57 0.99
Avoided per 100: 5.5   at the limits: 9.5 0.2
Standardization, traced: the risks if all of the records' patients received C or A, their ratio, its interval and the complications avoided per 100 patients.
The sliders start at the records: 80% of the patients on C are severe and the risk on A in severe patients is 40%, so the cards read a pooled ratio of 2.20 and a standardized ratio of 0.75. Raise the patients per treatment and both clouds of repeat studies tighten, but the pooled cloud stays on the harmful side. Move the severe share on C to 50% and the two ratios agree, because severity no longer decides who gets C. The range on the fourth card is read off the 40 simulated studies, so it is rougher than the calculated 0.57 to 0.99.

Weighting: the same answer by another road

Read first on this site:

Real records hold many confounders at once, such as age, kidney function and other diseases, and splitting patients by every combination soon leaves groups of one or two. Weighting copes by giving each patient one number; restriction to one kind of patient and a regression model are the other common routes.

That number is each patient's chance of receiving C, given their characteristics. In the records, 400 of the 500 severe patients received C, so a severe patient's chance was 0.80; a mild patient's was 0.20. This chance of treatment is called the propensity score. With many characteristics, a regression model estimates it.

Each patient then counts as many times as 1 divided by their chance of the treatment they actually received. A severe patient on C counts 1 / 0.80 = 1.25 times; a severe patient on A, rare in the records, counts 1 / 0.20 = 5.00 times. Rare patients stand in for the many like them who received the other treatment.

Weight the records, then compare

Each group's patients and complications are multiplied by its weight.

  1. The weights

    \[ \frac{1}{0.80}=1.25,\quad \frac{1}{0.20}=5.00 \]

    Severe patients on C and mild patients on A count 1.25 times; severe patients on A and mild patients on C count 5.00 times.

  2. The weighted C group

    \[ 400\times1.25+100\times5.00=1000,\quad 120\times1.25+3\times5.00=165 \]

    C now stands for 1,000 patients, half severe and half mild, with 165 complications: 16.5%.

  3. The weighted A group

    \[ 100\times5.00+400\times1.25=1000,\quad 40\times5.00+16\times1.25=220 \]

    A also stands for 1,000 patients, half severe, with 220 complications: 22.0%.

  4. Compare

    \[ \frac{165/1000}{220/1000}=\frac{16.5}{22.0}=0.75 \]

    The same 0.75 as standardization, and the same 5.5 complications avoided per 100 patients.

Result: Weighting builds a population in which severity no longer predicts who received C. Counting each patient 1 over the chance of the treatment they received, as above, is called inverse probability of treatment weighting, or IPTW.

Check balance, not a p-value

Read first on this site:

After weighting, check that the groups now look alike. The standardized difference compares a characteristic's share in two groups in units of its spread. Before weighting, 0.80 of the patients on C were severe against 0.20 of those on A: $\frac{0.80-0.20}{\sqrt{(0.80\times0.20+0.20\times0.80)/2}}=1.50$. After weighting both groups are half severe, and the difference is 0.00; a value above 0.1 is the usual sign of imbalance.

A p-value is the wrong check: it depends on the number of patients as much as on the size of the difference, so it cannot measure balance.

Matching, the other common use of the score, pairs each patient on C with a patient on A of similar score. In the records only 100 severe patients received A, so one-to-one matching finds partners for only 100 of the 400 severe patients on C, and the rest drop out. Matching then answers for patients like those who received C; weighting keeps all 1,000 patients and answers for the whole district, the question the model asks.

R code weighting.R
# Writes: stdout only. Each patient counted 1 / (chance of the treatment they actually received) times.
chance_c <- c(severe = 400 / 500, mild = 100 / 500)
weight_c <- 1 / chance_c; weight_a <- 1 / (1 - chance_c)
patients_w <- c(C = sum(c(400, 100) * weight_c), A = sum(c(100, 400) * weight_a))
events_w <- c(C = sum(c(120, 3) * weight_c), A = sum(c(40, 16) * weight_a))
severe_w <- c(400 * weight_c[["severe"]], 100 * weight_a[["severe"]]) / patients_w
smd <- function(p) abs(p[1] - p[2]) / sqrt((p[1] * (1 - p[1]) + p[2] * (1 - p[2])) / 2)
f <- function(x, d) formatC(x, d, format = "f")
cat("Weights on C, severe / mild:", f(weight_c, 2), "  on A:", f(weight_a, 2), "\n")
cat("Weighted patients C / A:", patients_w, "  complications:", events_w, "\n")
cat("Weighted risk C / A:", f(100 * events_w / patients_w, 1), "%\n")
cat("Severe share, standardized difference before / after:", f(smd(c(0.80, 0.20)), 2),
    f(smd(severe_w), 2), "(above 0.1 = imbalance)\n")
Output of the run weighting.log
Weights on C, severe / mild: 1.25 5.00   on A: 5.00 1.25
Weighted patients C / A: 1000 1000   complications: 165 220
Weighted risk C / A: 16.5 22.0 %
Severe share, standardized difference before / after: 1.50 0.00 (above 0.1 = imbalance)
Weighting, traced: the four weights, the weighted patients and complications on C and A, the weighted risks, and the standardized difference in the severe share before and after weighting.

Choose what to adjust for from the diagram, not from p-values

Read first on this site:

Records hold dozens of variables, and adjusting for the wrong one can create bias instead of removing it. Adjust for common causes of treatment and outcome, such as severity in Figure 1. Do not adjust for a mediator, a step on the path from C to the outcome: if C works partly by lowering a blood marker, comparing patients with the same marker level hides that part of the benefit, and the model would count fewer complications avoided than C prevents.

Do not adjust for a collider, a result that two causes share, such as a hospital admission that a side effect of C and severe disease can both cause. Among admitted patients the two causes become linked, so C can look worse or better than it is and the avoided complications per 100 would be wrong in the model.

A p-value screen cannot tell these roles apart: a strong mediator passes it, and a weak but real common cause may fail it. Draw the causes first; the list of variables follows from the drawing.

Bias: errors that more patients do not fix

Read first on this site:

Chance shrinks as a study grows; bias does not. Bias is a systematic error in how a study measures its patients or chooses whom to count. A study ten times bigger repeats the same error, only more precisely.

Suppose severity has been handled, so the true risks are 16.5% on C and 22.0% on A. Patients on C return every month for a blood test, so every complication reaches their records. Patients on A come back only when unwell, and the records catch 4 in 5 of their complications. The recorded risk on A becomes $0.8\times22.0=17.6\%$ and the ratio $16.5/17.6=0.94$: most of C's benefit has vanished.

This is information bias, and because the outcome was recorded differently in the two groups it is called differential misclassification. Ten times the patients would give the same 0.94 with a narrower interval.

If both groups lost 1 in 5 complications alike, called non-differential misclassification, the ratio would stay at 0.75, but the risks would fall to 13.2% and 17.6%, and the difference from 5.5 to 4.4 per 100 patients. A model that counts complications avoided needs complete counts, not only a fair ratio.

Start every patient's clock at the same moment

Read first on this site:

Selection bias comes from whom a study counts, and from when it starts counting. In records, C is often started some weeks after diagnosis. A patient who has a complication before that day never starts C, so the records file the complication under A. Patients on C are complication-free until their start date by construction.

Imagine 1,000 patients with the same 22.0% risk over the year, spread evenly, and a C that does nothing. Of them, 400 are due to start C at three months, and the other 600 never start it. Before then, 22 of those 400 have a complication and stay on A. Counted from diagnosis, C has 66 complications among 378 patients (17.5%), and A has 154 among 622 (24.8%): a ratio of 0.71 for a treatment with no effect.

The fix is to start everyone's clock at the same moment; this shared starting moment is called time zero. Counting both groups from three months, among patients still free of complications, A has 99 complications among 567 patients: 17.5%, the same as C, a ratio of 1.00.

The months before C started were not a benefit of C; they were time in which a complication could not count against C. This error is called immortal time bias.

The general guard is to write down the trial the records should imitate, with its eligibility, two treatment plans, time zero and outcome, and to analyse the records as if that trial had been run; this is called target-trial emulation [3]. ROBINS-I, a checklist for studies that are not randomized, walks through these errors one domain at a time [4].

R code timezero.R
# Writes: stdout only. 1,000 patients, same 22.0% one-year risk spread evenly; C does nothing.
starters <- 400; others <- 600; risk_year <- 0.22
early <- starters * risk_year * 3 / 12
risk_c <- (starters * risk_year * 9 / 12) / (starters - early)
risk_a <- (others * risk_year + early) / (others + early)
risk_a3 <- (others * risk_year * 9 / 12) / (others * (1 - risk_year * 3 / 12))
f <- function(x, d) formatC(x, d, format = "f")
cat("Complications before month 3 among those due to start C:", early, "\n")
cat("C from diagnosis:", starters * risk_year * 9 / 12, "of", starters - early, "\n")
cat("A from diagnosis:", others * risk_year + early, "of", others + early, "\n")
cat("A from month 3:", others * risk_year * 9 / 12, "of", others * (1 - risk_year * 3 / 12), "\n")
cat("From diagnosis, C/A:", f(100 * c(risk_c, risk_a), 1), "% ratio:", f(risk_c / risk_a, 2), "\n")
cat("Both from month 3, risk A:", f(100 * risk_a3, 1), "% ratio:", f(risk_c / risk_a3, 2), "\n")
Output of the run timezero.log
Complications before month 3 among those due to start C: 22
C from diagnosis: 66 of 378
A from diagnosis: 154 of 622
A from month 3: 99 of 567
From diagnosis, C/A: 17.5 24.8 % ratio: 0.71
Both from month 3, risk A: 17.5 % ratio: 1.00
Time zero, traced: the complications before C starts, the counts on C and A counted from diagnosis and from three months, the risks and the two ratios.

What the records did not measure

Standardization and weighting remove only the confounding that was measured. If doctors also judged frailty by eye and gave C to patients who looked stronger, the records hold no column for it. Confounding that remains after adjustment is called residual confounding.

One question helps: how strong would an unmeasured cause have to be to explain away the 0.75 completely? It would have to be linked both to receiving C and to having complications. Turn 0.75 into a ratio above 1, $1/0.75=1.333$, then compute $1.333+\sqrt{1.333\times0.333}=2.00$. A hidden cause would have to make complications 2.00 times as likely, and be 2.00 times as common in one treatment group as in the other, beyond severity, to move 0.75 to 1.00.

That number is called the E-value [5]. With the ratio turned above 1 written $RR^*$, $E=RR^*+\sqrt{RR^*(RR^*-1)}$. For the interval's end nearest 1, 0.99: $1/0.99=1.010$ and $1.010+\sqrt{1.010\times0.010}=1.11$, so a much weaker hidden cause could pull the interval across 1.

An E-value measures fragility; it is not a corrected estimate. A negative control helps too: an outcome C cannot affect, such as an injury from a fall. If patients on C also have fewer falls, something other than C is at work, for example healthier habits among patients who take their medicines, called the healthy-adherer effect.

Quantitative bias analysis goes one step further: it puts plausible sizes of a bias into the calculation, as the recording example did when it turned 0.75 into 0.94.

R code bias.R
# Writes: stdout only. Two checks on bias: uneven recording, and the E-value for the result.
true_c <- 16.5; true_a <- 22.0
found <- 0.8
recorded_a <- found * true_a
inverse <- 1 / c(0.75, 0.99)
e_value <- inverse + sqrt(inverse * (inverse - 1))
f <- function(x, d) formatC(x, d, format = "f")
cat("A loses 1 in 5: risk on A", f(recorded_a, 1), "%  ratio:", f(true_c / recorded_a, 2), "\n")
cat("Both lose 1 in 5, risks C / A:", f(found * c(true_c, true_a), 1), "%\n")
cat("Both lose 1 in 5, difference per 100:", f(found * (true_a - true_c), 1), "\n")
cat("1 / ratio for 0.75 and 0.99:", f(inverse, 3), "  minus 1:", f(inverse - 1, 3), "\n")
cat("E-value for 0.75 and 0.99:", f(e_value, 2), "\n")
Output of the run bias.log
A loses 1 in 5: risk on A 17.6 %  ratio: 0.94
Both lose 1 in 5, risks C / A: 13.2 17.6 %
Both lose 1 in 5, difference per 100: 4.4
1 / ratio for 0.75 and 0.99: 1.333 1.010   minus 1: 0.333 0.010
E-value for 0.75 and 0.99: 2.00 1.11
The bias checks, traced: the recorded risk on A and the ratio when only A loses 1 in 5 complications, the risks and the difference when both do, and the E-values for 0.75 and 0.99.

What goes into the economic model

The model needs complications avoided among the district's own patients. The three numbers on the desk give three different inputs. The table sets them side by side; every value in it was worked out above.

Read across each row: the risks, the risk ratio with its 95% interval, and what it means for 100 patients treated. Only the pooled row points the wrong way, because severity decided who received C.
SourceRisk on C vs ARisk ratio (95% interval)Per 100 patients treated
Trial12.12% vs 21.67%0.56 (0.25 to 1.26)9.55 fewer complications
Records, pooled24.6% vs 11.2%2.20 (1.64 to 2.94)13.4 more complications
Records, same patients16.5% vs 22.0%0.75 (0.57 to 0.99)5.5 fewer complications

Chance travels into the model; bias does not

Fed the pooled records, the model would count 13.4 extra complications per 100 patients for a treatment that prevents some. No cost or price can repair that input. The standardized 5.5 per 100 assumes that severity was the only confounder and that complications were recorded alike. It also assumes the district's patients are half severe, like the records'; if not, use the district's own mix.

Chance can travel into the model. Probabilistic sensitivity analysis (PSA) reruns the model many times with every uncertain input drawn from its distribution, so the result is a share of runs rather than one number. Each run gives an extra net benefit, the money value of the health gained minus the extra cost. When the extra net benefit averages 10,000 THB with a standard deviation of 40,000 THB, about 599 of 1,000 runs favour the treatment; the full lesson is in Probabilistic Sensitivity Analysis: From Parameter Distributions to CEAC.

Here each run draws the ratio from a distribution built from its interval, 0.57 to 0.99. At 0.57 the model counts $22.0\times(1-0.57)=9.5$ complications avoided per 100 patients and at 0.99 only 0.2, so most runs land between those two and a few beyond.

Bias cannot travel that way, because PSA carries chance only. Fed the pooled 2.20 and its interval, 1.64 to 2.94, almost every run would count harm, and the narrow spread of results would look reassuring [6]. Bias needs its own scenarios, such as the 0.94 from uneven recording, or a better input.

The trial and the standardized records now point the same way, and the trial's interval contains 0.75. How much to trust each input, and how sure the committee can be, is the question of certainty, taken up next (Beyond the Evidence Pyramid: GRADE Certainty and Choosing Effectiveness Inputs for Economic Models).

R code recaps.R
# Writes: stdout only. The re-running recap, traced: the series' own example of extra net benefit across 1,000 runs.
gain_mean <- 10000
gain_sd <- 40000
runs <- 1000
share <- pnorm(gain_mean / gain_sd)
cat("Extra net benefit, average (THB):", gain_mean, "\n")
cat("Extra net benefit, standard deviation (THB):", gain_sd, "\n")
cat("Runs of the model:", runs, "\n")
cat("Runs that favour the treatment:", round(share * runs), "\n")
Output of the run recaps.log
Extra net benefit, average (THB): 10000
Extra net benefit, standard deviation (THB): 40000
Runs of the model: 1000
Runs that favour the treatment: 599
The re-running recap, traced: the average and the standard deviation of the extra net benefit, the 1,000 runs and the runs that favour the treatment.

Terms as we use them

Chance (ความบังเอิญ (chance))
The error from which patients happened to be studied; it shrinks as the study grows.
95% confidence interval (ช่วงความเชื่อมั่น 95%)
The range of true effects the data cannot rule out; it reflects chance only.
Bias (อคติ (bias))
A systematic error in how a study measures or selects patients; a bigger study repeats it.
Confounding (ปัจจัยกวน (confounding))
A difference between treatment groups, such as severity, that also affects the outcome and mixes into the comparison.
DAG (แผนภาพเชิงสาเหตุ (DAG))
A diagram of assumed causes drawn as arrows that never loop back.
Mediator (ตัวแปรคั่นกลาง (mediator))
A step on the path from treatment to outcome; adjusting for it hides part of the effect.
Collider (ตัวแปรชน (collider))
A result shared by two causes; selecting on it links the causes falsely.
Standardization (การปรับมาตรฐาน (standardization))
Comparing treatments as if both were given to the same mix of patients.
Propensity score and IPTW (คะแนนความโน้มเอียงและการถ่วงน้ำหนักด้วยส่วนกลับของความน่าจะเป็นที่จะได้รับการรักษา (IPTW))
A patient's chance of receiving the treatment; IPTW counts each patient 1 / that chance times.
Standardized difference (ผลต่างมาตรฐาน (standardized difference))
The gap in a characteristic between groups in units of its spread; above 0.1 means imbalance.
Immortal time bias (อคติจากช่วงเวลาที่ไม่มีทางเกิดเหตุการณ์ (immortal time bias))
Time in which the outcome could not count against a treatment, wrongly counted as its benefit.
Target-trial emulation (การจำลองการทดลองเป้าหมาย (target-trial emulation))
Analysing records as the trial they should imitate: eligibility, plans, time zero and outcome.
E-value (E-value)
How strong a hidden cause would need to be, with both treatment and outcome, to explain an estimate away.

References

  1. Vandenbroucke JP, von Elm E, Altman DG, Gotzsche PC, Mulrow CD, Pocock SJ, Poole C, Schlesselman JJ, Egger M. Strengthening the Reporting of Observational Studies in Epidemiology (STROBE): explanation and elaboration. PLoS Med. 2007;4(10):e297. doi:10.1371/journal.pmed.0040297
  2. Muller CJ, MacLehose RF. Estimating predicted probabilities from logistic regression: different methods correspond to different target populations. Int J Epidemiol. 2014;43(3):962-970. doi:10.1093/ije/dyu029
  3. Hernan MA, Robins JM. Using big data to emulate a target trial when a randomized trial is not available. Am J Epidemiol. 2016;183(8):758-764. doi:10.1093/aje/kwv254
  4. Sterne JA, Hernan MA, Reeves BC, Savovic J, Berkman ND, Viswanathan M, Henry D, Altman DG, Ansari MT, Boutron I, Carpenter JR, Chan AW, Churchill R, Deeks JJ, Hrobjartsson A, Kirwan JR, Juni P, Loke YK, Pigott TD, Ramsay CR, Regidor D, Rothstein HR, Sandhu L, Santaguida PL, Schunemann HJ, Shea B, Shrier I, Tugwell P, Turner L, Valentine JC, Waddington H, Waters E, Wells GA, Whiting PF, Higgins JP. ROBINS-I: a tool for assessing risk of bias in non-randomised studies of interventions. BMJ. 2016;355:i4919. doi:10.1136/bmj.i4919
  5. VanderWeele TJ, Ding P. Sensitivity analysis in observational research: introducing the E-value. Ann Intern Med. 2017;167(4):268-274. doi:10.7326/M16-2607
  6. Briggs AH, Weinstein MC, Fenwick EAL, Karnon J, Sculpher MJ, Paltiel AD. Model parameter estimation and uncertainty: a report of the ISPOR-SMDM Modeling Good Research Practices Task Force-6. Value Health. 2012;15(6):835-842. doi:10.1016/j.jval.2012.04.014

The series, in learning order

  1. Health Economics Series Guide: Read the Evidence Before the Costs
  2. Incidence, Prevalence and the Right Denominator: The Epidemiology Beneath Cost-of-Illness and Markov Models
  3. Design, Model and Estimand: What Each Study Design Can Actually Estimate
  4. Risk Ratio, Odds Ratio, Risk Difference and NNT: One 2×2 Table, Four Answers
  5. The Hazard Ratio Is Not a Risk Ratio: Proportional Hazards, Restricted Mean Survival Time and Model Inputs
  6. Chance, Bias and Confounding: Why an Association Is Not Yet a Treatment Effect (this article)
  7. Beyond the Evidence Pyramid: GRADE Certainty and Choosing Effectiveness Inputs for Economic Models
  8. From Sensitivity to Cost per Case Detected: Predictive Values, Prevalence and the Economics of Screening
  9. Whose Cost, in Which Year? Perspective, Opportunity Cost, Inflation and Discounting
  10. QALY, DALY and the Utilities Behind Them: What Is Actually Being Measured
  11. ICER, Dominance and the Cost-Effectiveness Plane: Reading the Thai Threshold of 160,000 Baht per QALY
  12. Decision Trees, Markov Cohorts and Probabilistic Sensitivity Analysis: How a Model Turns Evidence into a Decision
  13. Cost-Effective Is Not Affordable, and Efficient Is Not Fair: Budget Impact and Equity
  14. Parameter Sourcing, Reference Cost Lists and Utility Catalogues When Local Data Are Sparse
  15. Early Health Technology Assessment, Headroom Pricing and Benefit-Package Decisions
  16. Communicating Health Economic Evidence: From Model Outputs to Policy Briefs

Key takeaways

  • Chance shrinks with size: ten times the trial's patients would narrow its interval from 0.25 to 1.26 down to 0.43 to 0.72.
  • Precise is not right: the pooled records give 2.20 (1.64 to 2.94) for a treatment that lowers the risk by a quarter.
  • Compare the same patients: standardization and weighting both give 16.5% against 22.0%, a risk ratio of 0.75.
  • Bias does not shrink with size: uneven recording turns 0.75 into 0.94, and counting from diagnosis makes a C that does nothing look like 0.71.
  • The model gets 5.5 complications avoided per 100 patients; re-running it across an interval carries chance only, so bias needs its own scenarios.

Related in the wiki: Design, Model and Estimand: What Each Study Design Can Actually Estimate · Beyond the Evidence Pyramid: GRADE Certainty and Choosing Effectiveness Inputs for Economic Models · ICER, Dominance and the Cost-Effectiveness Plane: Reading the Thai Threshold of 160,000 Baht per QALY · When IPTW Does Not Balance: Revise the Model or the Weights, Then Recheck Overlap and Balance · Emulating the Target Trial: A Framework of Strengthening Causal Inference in Observational Research

0
Message for International and Thai ReadersUnderstanding My Medical Context in ThailandRead more →Message for International and Thai ReadersUnderstanding My Broader Content Beyond MedicineRead more →

Comments

No comments yet. Be the first to share your thoughts.

Sign in to comment