Skip to content

Commit 97878d1

Browse files
authored
add variance-covariance matrix computation (#306)
1 parent bff39f4 commit 97878d1

File tree

4 files changed

+810
-19
lines changed

4 files changed

+810
-19
lines changed

R/classicalmetaanalysis.R

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,31 @@ ClassicalMetaAnalysis <- function(jaspResults, dataset = NULL, options, ...) {
5454
"permutationTest", "permutationTestIteration", "permutationTestType", "setSeed", "seed",
5555
# multilevel/multivariate specific
5656
"randomEffects", "randomEffectsSpecification",
57-
"computeCovarianceMatrix", "computeCovarianceMatrix"
57+
"computeCovarianceMatrix", "computeCovarianceMatrix",
58+
# multivariate effect size computation
59+
"varianceCovarianceMatrixType",
60+
"varianceCovarianceMatrixFile",
61+
"varianceCovarianceMatrixCorrelationMatrix",
62+
"varianceCovarianceMatrixSubcluster",
63+
"varianceCovarianceMatrixCluster",
64+
"varianceCovarianceMatrixForcePositiveDefiniteness",
65+
"varianceCovarianceMatrixCheckPositiveDefiniteness",
66+
"varianceCovarianceMatrixCorrelationMatrix",
67+
"varianceCovarianceMatrixConstruct",
68+
"varianceCovarianceMatrixConstructType",
69+
"varianceCovarianceMatrixTime1",
70+
"varianceCovarianceMatrixTime2",
71+
"varianceCovarianceMatrixGroup1",
72+
"varianceCovarianceMatrixGroup1",
73+
"varianceCovarianceMatrixGroupSize1",
74+
"varianceCovarianceMatrixGroupSize2",
75+
"varianceCovarianceMatrixConstructCorrelationMatrix",
76+
"varianceCovarianceMatrixConstructCorrelationMatrixValue",
77+
"varianceCovarianceMatrixConstructCorrelationMatrixFilePath",
78+
"varianceCovarianceMatrixConstructTypeCorrelationMatrix",
79+
"varianceCovarianceMatrixConstructTypeCorrelationMatrixValue",
80+
"varianceCovarianceMatrixConstructTypeCorrelationMatrixFilePath",
81+
"varianceCovarianceMatrixTimeLag1Correlation"
5882
)
5983
.maForestPlotDependencies <- c(
6084
# do not forget to add variable carrying options to the .maDataPlottingDependencies
@@ -183,15 +207,25 @@ ClassicalMetaAnalysis <- function(jaspResults, dataset = NULL, options, ...) {
183207

184208
.hasErrors(
185209
dataset = dataset,
186-
type = c("infinity", "observations", "variance"),
210+
type = c("infinity", "observations"),
187211
all.target = c(
188212
options[["effectSize"]],
189-
options[["effectSizeStandardError"]],
190-
options[["predictors"]][options[["predictors.types"]] == "scale"]
213+
options[["effectSizeStandardError"]]
191214
),
192215
observations.amount = "< 2",
193216
exitAnalysisIfErrors = TRUE)
194217

218+
# do not check effect sizes / standard errors for 0 variance
219+
otherVariable <- options[["predictors"]][options[["predictors.types"]] == "scale"]
220+
if (length(otherVariable) > 0) {
221+
.hasErrors(
222+
dataset = dataset,
223+
type = c("infinity", "observations", "variance"),
224+
all.target = otherVariable,
225+
observations.amount = "< 2",
226+
exitAnalysisIfErrors = TRUE)
227+
}
228+
195229
if (length(options[["effectSizeModelTerms"]]) > 0)
196230
.hasErrors(
197231
dataset = dataset,

R/classicalmetaanalysiscommon.R

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@
2222

2323

2424
# TODO:
25-
# Forest plot
26-
# - allow aggregation of studies by a factor (then show simple REML aggregation within and overlaying shaded estimates)
2725
# AIC/BIC Model-averaging
2826
# Diagnostics
2927
# - model re-run on presence of influential cases
@@ -97,11 +95,14 @@
9795
if (options[["diagnosticsResidualFunnel"]])
9896
.maResidualFunnelPlot(jaspResults, options)
9997

100-
10198
# additional
10299
if (options[["showMetaforRCode"]])
103100
.maShowMetaforRCode(jaspResults, options)
104101

102+
# export the variance-covariance matrix if requested
103+
if (.maIsMultilevelMultivariate(options) && options[["varianceCovarianceMatrixSaveComputedVarianceCovarianceMatrix"]] != "")
104+
.mammExportVarianceCovarianceMatrix(dataset, options)
105+
105106
return()
106107
}
107108

@@ -154,10 +155,11 @@
154155
subgroupIndx <- dataset[[options[["subgroup"]]]] == subgroupLevel
155156
subgroupData <- droplevels(dataset[subgroupIndx, ])
156157

157-
# forward NAs information
158+
# forward NAs information and additional attributes
158159
tempNasIds <- attr(dataset, "NasIds")[!attr(dataset, "NasIds")]
159-
attr(subgroupData, "NAs") <- sum(tempNasIds[subgroupIndx])
160-
attr(subgroupData, "NasIds") <- tempNasIds[subgroupIndx]
160+
attr(subgroupData, "NAs") <- sum(tempNasIds[subgroupIndx])
161+
attr(subgroupData, "NasIds") <- tempNasIds[subgroupIndx]
162+
attr(subgroupData, "subgroupIndx") <- subgroupIndx
161163

162164
# fit the model
163165
fitOutput[[paste0("subgroup", subgroupLevel)]] <- .maFitModelFun(subgroupData, options, subgroupName = as.character(subgroupLevel))
@@ -178,16 +180,17 @@
178180

179181
# specify the effect size and outcome
180182
if (options[["module"]] == "metaAnalysis") {
183+
# specify the univariate input
181184
rmaInput <- list(
182185
yi = as.name(options[["effectSize"]]),
183186
sei = as.name(options[["effectSizeStandardError"]]),
184187
data = dataset
185188
)
186189
} else if (options[["module"]] == "metaAnalysisMultilevelMultivariate") {
187-
# TODO: extend to covariance matrices
190+
# specify the multivariate input
188191
rmaInput <- list(
189192
yi = as.name(options[["effectSize"]]),
190-
V = as.name("samplingVariance"), # precomputed on data load
193+
V = if (.mammVarianceCovarianceMatrixReady(options)) .mammGetVarianceCovarianceMatrix(dataset, options) else as.name("samplingVariance"),
191194
data = dataset
192195
)
193196
}
@@ -757,6 +760,14 @@
757760
)
758761
}
759762

763+
# add multivariate settings notes
764+
if (.maIsMultilevelMultivariate(options)) {
765+
multivariateReadyNotes <- attr(.mammVarianceCovarianceMatrixReady(options), "messages")
766+
for (i in seq_along(multivariateReadyNotes)) {
767+
testsTable$addFootnote(multivariateReadyNotes[i])
768+
}
769+
}
770+
760771
# bind and clean rows
761772
tests <- .maSafeRbind(tests)
762773
tests <- .maSafeOrderAndSimplify(tests, "test", options)
@@ -3316,10 +3327,15 @@
33163327
data = as.name("dataset")
33173328
)
33183329
} else if (options[["module"]] == "metaAnalysisMultilevelMultivariate") {
3319-
# TODO: extend to covariance matrices
3330+
3331+
if (.mammVarianceCovarianceMatrixReady(options)) {
3332+
vcalcInput <-.mammGetVarianceCovarianceMatrix(NULL, options, returnCall = TRUE)
3333+
vcalcInput$data <- as.name("dataset")
3334+
}
3335+
33203336
rmaInput <- list(
33213337
yi = as.name(options[["effectSize"]]),
3322-
V = paste0(options[["effectSizeStandardError"]], "^2"), # precomputed on data load
3338+
V = if (.mammVarianceCovarianceMatrixReady(options)) "effectSizeVarianceCovarianceMatrix" else paste0(options[["effectSizeStandardError"]], "^2"),
33233339
data = as.name("dataset")
33243340
)
33253341
}
@@ -3401,6 +3417,19 @@
34013417
fit <- paste0("fit <- rma(\n\t", paste(names(rmaInput), "=", rmaInput, collapse = ",\n\t"), "\n)\n")
34023418
}
34033419

3420+
if (.maIsMultilevelMultivariate(options) && .mammVarianceCovarianceMatrixReady(options)) {
3421+
if (options[["varianceCovarianceMatrixType"]] == "precomputed") {
3422+
fit <- paste0(
3423+
paste0("effectSizeVarianceCovarianceMatrix <- ", vcalcInput[["file"]], "\n"), "\n",
3424+
fit
3425+
)
3426+
} else {
3427+
fit <- paste0(
3428+
paste0("effectSizeVarianceCovarianceMatrix <- vcalc(\n\t", paste(names(vcalcInput), "=", vcalcInput, collapse = ",\n\t"), "\n)\n"), "\n",
3429+
fit
3430+
)
3431+
}
3432+
}
34043433

34053434
# add clustering if specified
34063435
if (options[["clustering"]] != "") {

0 commit comments

Comments
 (0)