IntHout 2014 - Converting DL Results to HKSJ Worked Examples

Summary

Given only a published DL forest plot (effect sizes and DL weights , e.g. in percent), you can recompute a HKSJ interval and -value by hand: form , divide by , take the square root for the SE, and use a quantile. For a zinc/common-cold review (, ) this turns DL into HKSJ ; for a log-hazard-ratio example (, ) the results barely change.

Overview

The conversion applies to continuous outcomes and to log-transformed ratio outcomes (RR, OR, HR, Poisson rate). An Excel file (Additional file 1) and R code (Appendix 3) are provided. Only three columns are needed: study ID, study result and DL weight .

Main Content

Recipe

Post-hoc HKSJ procedure (Examples 1-2)

  1. SE. (a) With overall DL estimate , compute for each study. (b) Sum them and divide by . (c) Divide by . This is the HKSJ variance of the pooled effect. (d) Square root = SE. (For ratio outcomes, work on the natural-log scale: , .)
  2. CI. Half-width = SE (Excel TINV(0.05,k-1), SPSS IDF.T(.975,k-1), SAS tinv(.975,k-1)); CI = half-width (exponentiate for ratios).
  3. -value. ; two-sided from (Excel TDIST(|t|,k-1,2); SPSS 2*(1-CDF.T(|t|,k-1)); SAS cdf('T',t,k-1)).

Example 1: continuous outcome (zinc for the common cold)

Cochrane review (Singh and Das 2011), outcome severity of cold symptoms, 513 participants, SMD. DL: 5 studies, , .

Study (SMD) (DL)
Kurugol 2006a-0.0424.00.12252.94
Kurugol 2007-0.0722.20.10242.27
Petrus 1998-0.3121.30.00640.14
Prasad 2000-1.3615.50.940914.58
Prasad 2008-0.5417.00.02250.38
Sum 100.0Sum 20.31

Steps: ; ; SE ; ; half-width ; CI ; ; two-sided .

MethodEstimate95% CITest
DLSMD -0.39[-0.77, -0.02],
HKSJSMD -0.39[-1.02, 0.24], df 4,

“The results of the DL and HKSJ analyses differ substantially”: significance disappears.

R (metafor), Appendix 3: y <- c(-0.04,-0.07,-0.31,-1.36,-0.54); w <- c(24.0,22.2,21.3,15.5,17.0); rma.uni(y, vi=1/w, method="FE", knha=TRUE). The DL weights are supplied as fixed-effect weights with knha=TRUE, so that the HKSJ adjustment is applied to random-effects weights; the resulting warnings (“HKSJ not meant to be used with fixed effects”) can be ignored. Output (Table 5): estimate -0.3938, SE 0.2254, , , CI (the hand calculation rounds to 1.73 and 0.16).

Example 2: log-transformed outcome (hazard ratio, post-remission therapy for adult ALL, donor vs no donor)

Cochrane review (Pidala et al. 2011). DL: 10 studies, , . DL pooled HR 0.86 [0.77, 0.97], , .

StudyHR
Cornelissen 20090.815.0-0.210.000.02
De Witte 19940.672.1-0.400.060.13
Fielding 20090.8011.5-0.220.010.06
Goldstone 20080.9146.7-0.090.000.15
Hunault 20040.562.9-0.580.180.53
Labar 20040.989.3-0.020.020.16
Ribera 20051.243.90.220.130.52
Sebban 19940.7512.7-0.290.020.24
Takeuchi 20020.953.9-0.050.010.04
Ueda 19980.662.0-0.420.070.14
()Sum 100.0Sum 1.99

Steps: ; ; SE ; ; half-width on ln scale ; ln CI ; HR CI ; ; .

MethodHR95% CITest
DL0.86[0.77, 0.97],
HKSJ (hand)0.86[0.77, 0.96], df 9,
HKSJ (R, Table 6)0.8643[0.7772, 0.9613]ln estimate -0.1458, SE 0.0470, ,

“The results of the DL and HKSJ analyses hardly differ”, consistent with homogeneity (). The small hand-versus-R gap ( vs ) comes from intermediate rounding of .

Why HKSJ can be narrower than DL here (computed, not in the paper)

The DL SE implied by the DL statistics is (also from the DL CI: ). The HKSJ SE is , so : with the observed spread is smaller than the weights predict, so the HKSJ variance is smaller than the DL one. The larger quantile (2.26 vs 1.96) roughly cancels this: half-width vs on the log scale.

Examples

Independent Python reproduction

Both examples reproduce exactly: Example 1 gives , SE 0.22536, , , CI , and weighted sum 20.31; Example 2 gives ln estimate -0.14580, SE 0.046985, , , HR 0.8643 [0.7772, 0.9613].

import numpy as np
from scipy import stats
def hksj_from_dl(y, w, log_scale=False):
    y = np.log(y) if log_scale else np.asarray(y); w = np.asarray(w); k = len(y)
    yb = (w*y).sum()/w.sum(); var = (w*(y-yb)**2).sum()/((k-1)*w.sum()); se = var**.5
    tq = stats.t.ppf(.975, k-1); t = yb/se; p = 2*stats.t.sf(abs(t), k-1)
    ci = (yb-tq*se, yb+tq*se)
    return (np.exp(yb), np.exp(ci[0]), np.exp(ci[1]), t, p) if log_scale else (yb, *ci, t, p)
hksj_from_dl([-0.04,-0.07,-0.31,-1.36,-0.54], [24.0,22.2,21.3,15.5,17.0])               # (-0.394, -1.019, 0.232, -1.747, 0.1555)
hksj_from_dl([.81,.67,.80,.91,.56,.98,1.24,.75,.95,.66], [5.0,2.1,11.5,46.7,2.9,9.3,3.9,12.7,3.9,2.0], log_scale=True)

Connections

  • Marketing: when a vendor deck gives only a forest plot of per-test lift estimates and percent weights, this recipe lets an analyst recompute a -based interval without the raw data. Caveat: the weights must be the random-effects weights from the vendor’s analysis.
  • Same machinery as knha=TRUE (Viechtbauer 2010 - Fitting Models with rma, Moderators and Knapp-Hartung).

See Also