Skip to content
Prev 4464 / 5636 Next

[R-meta] Computing Effect Size for Difference in Differences with Different Populations

Dear Mika,

You can certainly use both effect size measures and see to what extent the
choice can affect the results.

But if the traditions in your area of research allow, it may also be worth
running your model using the usual standardized mean differences (SMDs) as
the effect size of choice for each group at each time point and then
conduct appropriate contrasts to get the difference in differences (DID)
meta-analytically.

I believe in the **dev. version** of metafor, Wolfgang has recently added a
new function called emmprep() that in conjunction with library emmeans may
be helpful to achieve this relatively easily.

For example, in the data below (consisting of 3 groups and 3 time points),
you can compute the DID across 3 groups for long-term gains (i.e.,
differences in gains between time1 and time3) as follows:

# install dev version of metafor
library(emmeans)

dat$effect <- 1:nrow(dat)

# Model:
a1 <- rma.mv(smd ~group*time, V=vi, random = list(~time|study, ~1|effect),
data=dat,
            dfs = "contain")

# New function in metafor:
sav1 <- emmprep(a1)

# Marginal means:
emms <- emmeans(sav1, ~group*time)

# Desired contrasts among marginal means:
contrast(emms, list("Long-term: Gain(gr2) - Gain(gr1)" =
c(1,-1,0,0,0,0,-1,1,0),  # length must match #of rows in emms
                                "Long-term: Gain(gr2) - Gain(gr3)" =
c(0,-1,1,0,0,0,0,1,-1),
                                 "Long-term: Gain(gr3) - Gain(gr1)" =
c(1,0,-1,0,0,0,-1,0,1)
             ))

The above steps assume that you are interested in comparing the groups at
the final stage of the studies (time3), but see differences in their
initial status (time1) that demand taking those differences into account.
Similar steps can be taken to target differences at time2 taking into
account the initial differences.

The above procedure could be used with other models as well. For instance,
pretending that dat is not multilevel in structure, we could fit the
following model and repeat the above steps.

a2 <- rma(smd ~group*time, vi=vi, data=dat, test = "knha")

Kind regards,
Reza

# Data
dat <- structure(list(study = c(1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3,
                                    3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5,
5, 5, 5, 5, 5, 5, 5, 5,
                                    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 6, 6, 6, 6, 6, 6,
                                    7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9,
9, 10, 10, 10, 10, 10,10),
                          smd = c(1.681, 4.122, 2.6, 3.457, 1.546, 3.072,
0.22, 3.545,
                                4.454, 0.624, 0.047, 0.306, 1.48, 1.2,
1.483, 1.054, 0.638, 0.998,
                                -0.31, -0.079, 0.955, 0.721, 1.531, 0.974,
-0.104, 0.235, -0.11,
                                -0.005, -0.117, 0.384, -0.194, 0.299,
0.452, 0.66, 0.268, 0.132,
                                0.078, 0.254, -0.339, -0.057, 0.482, 0.278,
0.104, 0.253, 0.107,
                                0.652, 0.386, 0.134, -0.329, -0.366,
-0.011, -0.359, 0, -1.279,
                                -0.178, -0.066, -0.149, -0.547, -0.173,
-0.279, 0.795, 0.172,
                                0.422, 0.461, 1.591, 1.001, -0.352, 0.473,
0.453, 0.3, 0.798,
                                0.868, 0.897, 0.862),
                           vi = c(0.208, 0.481, 0.284, 0.384, 0.2,
                                  0.335, 0.08, 0.206, 0.278, 0.114, 0.106,
0.101, 0.138, 0.125,
                                  0.127, 0.124, 0.111, 0.112, 0.072, 0.073,
0.08, 0.077, 0.092,
                                  0.081, 0.048, 0.049, 0.048, 0.048, 0.047,
0.047, 0.047, 0.047,
                                  0.049, 0.051, 0.049, 0.048, 0.048, 0.049,
0.049, 0.048, 0.048,
                                  0.047, 0.047, 0.047, 0.047, 0.049, 0.047,
0.047, 0.112, 0.112,
                                  0.11, 0.112, 0.11, 0.132, 0.101, 0.099,
0.101, 0.103, 0.101,
                                  0.1, 0.196, 0.168, 0.186, 0.172, 0.239,
0.189, 0.136, 0.138,
                                  0.149, 0.135, 0.157, 0.146, 0.16, 0.146),
                          group = structure(c(1L, 2L, 1L, 2L, 1L, 2L, 1L,
1L, 1L, 1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L,
                                              3L, 1L, 2L, 1L, 2L, 1L, 2L,
1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 1L,
                                              1L, 1L, 1L, 1L, 1L, 1L, 1L,
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 1L,
                                              1L, 1L, 1L, 1L, 1L, 1L, 2L,
1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L,
                                              2L, 1L, 1L, 1L, 2L, 1L, 2L,
1L, 2L), levels = c("1", "2", "3"
                                              ), class = "factor"),
                         time = structure(c(1L, 1L, 2L, 2L, 3L, 3L, 1L, 2L,
3L, 1L, 1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L, 1L, 1L, 2L,
                                            2L, 3L, 3L, 1L, 1L, 1L, 1L, 1L,
1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L,
                                            3L, 3L, 3L, 2L, 2L, 2L, 2L, 3L,
3L, 3L, 3L, 1L, 1L, 2L, 2L, 3L,
                                            3L, 1L, 1L, 2L, 2L, 3L, 3L, 1L,
1L, 2L, 2L, 3L, 3L, 1L, 2L, 1L,
                                            1L, 2L, 2L, 3L, 3L), levels =
c("1", "2", "3"), class = "factor")),
                         class = "data.frame", row.names = c(NA, -74L))


On Thu, Mar 16, 2023 at 5:47?PM Mika Manninen via R-sig-meta-analysis <
r-sig-meta-analysis at r-project.org> wrote: