This function performs a mixed-effects (random-effects model within subgroups, fixed-effect model between subgroups) subgroup analysis using meta objects.

Usage

subgroup.analysis.mixed.effects(x, subgroups, exclude = "none")

Arguments

x

An object of class meta, generated by the metabin, metagen, metacont, metacor, metainc, or metaprop function.

subgroups

A character vector of the same length as the number of studies within the meta-analysis, with a unique code for the subgroup each study belongs to. Must have the same order as the studies in the meta object.

exclude

Single string or concatenated array of strings. The name(s) of the subgroup levels to be excluded from the subgroup analysis. If "none" (default), all subgroup levels are used for the analysis.

Value

Returns a list with five objects:

• within.subgroup.results: The pooled effect size for each subgroup and corresponding measures of heterogeneity ( Q and I2). If the summary measure sm is defined as one of "RR", "RD", "OR", "ASD", "HR" or "IRR" in the meta object provided in x, the backtransformed (exponentiated) pooled effect for each subgroup effect size along with the 95% confidence interval is also provided.

• subgroup.analysis.results: The results for the Q-test for subgroup differences, its degrees of freedom df and p-value.

• m.random: An object of class meta containing the results of the random-effects model applied for pooling results in each subgroup in the first step.

• method.tau: The $$\tau^2$$ estimator used for within-subgroup pooling (inherited from the meta object provided in x).

• k: The total number of included studies.

Details

This function conducts a test for differences in effect sizes between subgroups of a meta-analysis. The function implements a mixed-effect model, in which the overall effect size for each subgroup is calculated using a random-effect model, and the test for subgroup differences is conducted using a fixed-effect model. The implementation follows the fixed-effects (plural) model described in Borenstein and Higgins (2013).

This model is appropriate for subgroup tests when the subgroup levels under study are assumed to be exhaustive for the characteristic at hand, and are not randomly chosen instances of a "population" of subgroup levels. For example, the fixed-effects (plural) model used in the function is valid when differences between studies published before and after a certain year are considered as a (binary) subgroup level. When subgroup levels can be assumed to be random samples from a distribution of subgroup levels, a random-effects model is more appropriate, and may be calculated using the update.meta function.

The function uses the study effect sizes TE and their standard error seTE of the provided meta object to perform the subgroup analyses. Specifications of the summary measure sm are inherited and used to backtransform log-transformed effect sizes to their original metrics if necessary.

Results can be inspected by plugging the function output into the summary function. Forest plots can be generated using forest. Additional arguments of the forest.meta function can be passed to the forest function for additional styling.

References

Harrer, M., Cuijpers, P., Furukawa, T.A, & Ebert, D. D. (2019). Doing Meta-Analysis in R: A Hands-on Guide. DOI: 10.5281/zenodo.2551803. Chapter 7.

Borenstein, M. & Higgins, J. P. T. (2013). Meta-Analysis and Subgroups. Prevention Science, 14 (2): 134–43.

multimodel.inference

Author

Mathias Harrer & David Daniel Ebert

Examples

# Example 1: Hedges' g as effect size, precalculated effect sizes
suppressPackageStartupMessages(library(dmetar))
suppressPackageStartupMessages(library(meta))
data("ThirdWave")
ThirdWave = ThirdWave[c(1,2,3,5,9,18),]

m1 <- metagen(TE = TE,
seTE = seTE,
studlab = paste(ThirdWave$Author), data=ThirdWave, comb.fixed = FALSE, method.tau = "PM", sm = "SMD") #> Warning: Use argument 'fixed' instead of 'comb.fixed' (deprecated). sgame1 = subgroup.analysis.mixed.effects(x = m1, subgroups = ThirdWave$TypeControlGroup)
#> Warning: Use argument 'fixed' instead of 'comb.fixed' (deprecated).
#> Warning: Use argument 'random' instead of 'comb.random' (deprecated).
#> Warning: Use argument 'subgroup' instead of 'byvar' (deprecated).
#> Warning: Use argument 'fixed' instead of 'comb.fixed' (deprecated).
#> Warning: Use argument 'subgroup' instead of 'byvar' (deprecated).
summary(sgame1)
#> Subgroup Results:
#> --------------
#>                  k       SMD        SE  LLCI  ULCI             p         Q   I2
#> WLC              3 0.9154106 0.4253639 0.082 1.749 0.03139224728 13.058904 0.85
#> information only 3 0.4015895 0.1003796 0.205 0.598 0.00006315313  1.144426 0.00
#>                  I2.lower I2.upper
#> WLC                  0.55     0.95
#> information only     0.00     0.90
#>
#> Test for subgroup differences (mixed/fixed-effects (plural) model):
#> --------------
#>                       Q df        p
#> Between groups 1.382187  1 0.239729
#>
#> - Total number of studies included in subgroup analysis:  6
#> - Tau estimator used for within-group pooling:  PM

# Example 2: Hedges' g as effect size, raw effect data
suppressPackageStartupMessages(library(meta))
data(amlodipine)

# Create an arbitrary subgroup for illustration purposes
amlodipine$subgroup = rep(c("A","B"),4) m2 <- metacont(n.amlo, mean.amlo, sqrt(var.amlo), n.plac, mean.plac, sqrt(var.plac), data=amlodipine, studlab=amlodipine$study,
sm = "SMD")

sgame2 = subgroup.analysis.mixed.effects(x = m2, subgroups = amlodipine$subgroup) #> Warning: Use argument 'fixed' instead of 'comb.fixed' (deprecated). #> Warning: Use argument 'random' instead of 'comb.random' (deprecated). #> Warning: Use argument 'subgroup' instead of 'byvar' (deprecated). #> Warning: Use argument 'fixed' instead of 'comb.fixed' (deprecated). #> Warning: Use argument 'subgroup' instead of 'byvar' (deprecated). summary(sgame2) #> Subgroup Results: #> -------------- #> k SMD SE LLCI ULCI p Q I2 I2.lower #> A 4 0.4970586 0.1302176 0.242 0.752 0.0001350091 3.749695 0.20 0 #> B 4 0.3163117 0.1642004 -0.006 0.638 0.0540574677 5.330220 0.44 0 #> I2.upper #> A 0.88 #> B 0.81 #> #> Test for subgroup differences (mixed/fixed-effects (plural) model): #> -------------- #> Q df p #> Between groups 0.7438662 1 0.3884252 #> #> - Total number of studies included in subgroup analysis: 8 #> - Tau estimator used for within-group pooling: REML # Example 3: Risk ratio as effect size, binary outcome data, exlcude one level suppressPackageStartupMessages(library(meta)) data(Olkin95) # Create an arbitrary subgroup for illustration purposes Olkin95$subgroup = c(rep(c("A","B"), 30), rep("C",10))

m3 <- metabin(event.e, n.e, event.c, n.c,
data = Olkin95, studlab = Olkin95$author, method = "Inverse") # Use shorthand sgame3 = sgame(x = m3, subgroups = Olkin95$subgroup,
exclude = "B")
#> Warning: Use argument 'fixed' instead of 'comb.fixed' (deprecated).
#> Warning: Use argument 'random' instead of 'comb.random' (deprecated).
#> Warning: Use argument 'subgroup' instead of 'byvar' (deprecated).
#> Warning: Use argument 'fixed' instead of 'comb.fixed' (deprecated).
#> Warning: Use argument 'subgroup' instead of 'byvar' (deprecated).
#> Warning: Use argument 'fixed' instead of 'comb.fixed' (deprecated).
#> Warning: Use argument 'subgroup' instead of 'byvar' (deprecated).
summary(sgame3)
#> Subgroup Results:
#> --------------
#>    k         TE       seTE        RR  LLCI  ULCI            p        Q   I2
#> A 30 -0.2236279 0.06797886 0.7996126 0.700 0.914 0.0010030546 37.15381 0.22
#> C 10 -0.3378363 0.09118373 0.7133121 0.597 0.853 0.0002113859 10.65963 0.16
#>   I2.lower I2.upper
#> A        0     0.50
#> C        0     0.57
#>
#> Test for subgroup differences (mixed/fixed-effects (plural) model):
#> --------------
#>                       Q df         p
#> Between groups 1.008345  1 0.3152996
#>
#> - Total number of studies included in subgroup analysis:  40
#> - Tau estimator used for within-group pooling:  REML

# Example 4: IRR as effect size, incidence data
suppressPackageStartupMessages(library(meta))
data(smoking)

# Create an arbitrary subgroup for illustration purposes
smoking$subgroup = c(rep(c("A"), 4), rep(c("B"), 3)) m4 <- metainc(d.smokers, py.smokers, d.nonsmokers, py.nonsmokers, data=smoking, studlab=study, sm="IRR") sgame4 = subgroup.analysis.mixed.effects(x = m4, subgroups = smoking$subgroup)
#> Warning: Use argument 'fixed' instead of 'comb.fixed' (deprecated).
#> Warning: Use argument 'random' instead of 'comb.random' (deprecated).
#> Warning: Use argument 'subgroup' instead of 'byvar' (deprecated).
#> Warning: Use argument 'fixed' instead of 'comb.fixed' (deprecated).
#> Warning: Use argument 'subgroup' instead of 'byvar' (deprecated).
summary(sgame4)
#> Subgroup Results:
#> --------------
#>   k        TE       seTE      IRR  LLCI  ULCI
#> A 4 0.5102054 0.05187149 1.665633 1.505 1.844
#> B 3 0.4921778 0.01363593 1.635875 1.593 1.680
#>                                                                                                                                                                                                                                                                                                      p
#> A 0.00000000000000000000007881949876651695761105211927243381005002700948803938336169187025420646008910807722713798284530639648437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
#> B 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000279883
#>            Q   I2 I2.lower I2.upper
#> A 42.2826988 0.93     0.85     0.97
#> B  0.6826077 0.00     0.00     0.90
#>
#> Test for subgroup differences (mixed/fixed-effects (plural) model):
#> --------------
#>                        Q df         p
#> Between groups 0.1129792  1 0.7367775
#>
#> - Total number of studies included in subgroup analysis:  7
#> - Tau estimator used for within-group pooling:  REML

if (FALSE) {
# Generate Forest Plot
# Additional arguments of the meta::forest.meta can be supplied
forest(sgame1, col.diamond = "darkgreen")
forest(sgame2)
forest(sgame3)
forest(sgame4)
}