Skip to content

Commit

Permalink
Add osmasem2 and related methods
Browse files Browse the repository at this point in the history
  • Loading branch information
mikewlcheung committed Jul 27, 2024
1 parent 801d5db commit f4f500d
Show file tree
Hide file tree
Showing 15 changed files with 1,433 additions and 665 deletions.
4 changes: 2 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
Package: metaSEM
Type: Package
Title: Meta-Analysis using Structural Equation Modeling
Version: 1.4.3
Date: 2024-07-13
Version: 1.4.4
Date: 2024-07-27
Depends: R (>= 3.4.0), OpenMx
Imports: Matrix, MASS, ellipse, graphics, stats, utils, mvtnorm, numDeriv, lavaan
Suggests: metafor, semPlot, R.rsp, testthat, matrixcalc
Expand Down
4 changes: 4 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ S3method(summary, CorPop)
S3method(summary, Cor3L)
S3method(summary, bootuniR2)
S3method(summary, osmasem)
S3method(summary, osmasem2)
S3method(summary, mxRAMmodel)
# S3method(summary, osmasem3L)
# S3method(summary, tssemRobust1)
Expand All @@ -38,6 +39,7 @@ S3method(anova, meta3LFIML)
S3method(anova, wls)
S3method(anova, reml)
S3method(anova, osmasem)
S3method(anova, osmasem2)
S3method(anova, mxRAMmodel)
# S3method(anova, osmasem3L)

Expand All @@ -50,6 +52,7 @@ S3method(coef, meta)
S3method(coef, meta3LFIML)
S3method(coef, reml)
S3method(coef, osmasem)
S3method(coef, osmasem2)
S3method(coef, mxRAMmodel)
# S3method(coef, osmasem3L)
# S3method(coef, tssemRobust1)
Expand All @@ -63,6 +66,7 @@ S3method(vcov, meta)
S3method(vcov, meta3LFIML)
S3method(vcov, reml)
S3method(vcov, osmasem)
S3method(vcov, osmasem2)
S3method(vcov, mxRAMmodel)
# S3method(vcov, osmasem3L)
# S3method(vcov, tssemRobust1)
Expand Down
5 changes: 5 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
Release 1.4.4 (Jul 27, 2024)
====================================
* Add osmasem2() and friends.
* Add mean data in issp05.

Release 1.4.3 (Jul 13, 2024)
====================================
* Support means in Cor2DataFrame().
Expand Down
64 changes: 45 additions & 19 deletions R/Cor2DataFrame.R
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ Cor2DataFrame <- function(x, n, v.na.replace=TRUE, cor.analysis=TRUE,
acov=c("weighted", "individual", "unweighted"),
Means, row.names.unique=FALSE, append.vars=TRUE,
asyCovOld=FALSE, ...) {


acov <- match.arg(acov, c("weighted", "individual", "unweighted"))

## x is a list of "data", "n", ...
if (all(c("data", "n") %in% names(x))) {
my.cov <- x$data
Expand All @@ -24,16 +26,34 @@ Cor2DataFrame <- function(x, n, v.na.replace=TRUE, cor.analysis=TRUE,
my.df <- list2matrix(x=my.cov, diag=TRUE)
}

## NA is not allowed in definition variables
## Check if there are NAs in my.cov and replace them with the weighted or unweighted averages
if (any(sapply(my.cov, is.na)) & v.na.replace) {
## Replace NA with 0 before calculations
my.x <- lapply(my.cov, function(z) {z[is.na(z)] <- 0; z} )
if (acov=="unweighted") {
## x: original covariance matrices in the input
## Unweighted means = sum of r/(no. of studies)
cov.mean <- Reduce("+", my.x)/pattern.na(x, show.na = FALSE)
} else if (acov=="weighted") {
my.x <- mapply("*", my.x, n, SIMPLIFY = FALSE)
## Weighted means = Cummulative sum of r*n/(sum of n)
cov.mean <- Reduce("+", my.x)/pattern.n(x, n)
}

my.cov <- lapply(my.cov,
function(z) {
na.index <- is.na(z)
z[na.index] <- cov.mean[na.index]
z})
}

if (asyCovOld) {
acovR <- asyCovOld(x=my.cov, n=n, cor.analysis=cor.analysis, acov=acov, ...)
} else {
acovR <- asyCov(x=my.cov, n=n, cor.analysis=cor.analysis, acov=acov, ...)
}

## NA is not allowed in definition variables
## They are replaced by 1e10
if (v.na.replace) acovR[is.na(acovR)] <- 1e10

## x is a list of "data", "n", and moderators, and append
## Append the moderators x[-c(1,2)] into data
if (all(c(c("data", "n") %in% names(x), length(names(x))>2, append.vars))) {
Expand All @@ -56,20 +76,16 @@ Cor2DataFrame <- function(x, n, v.na.replace=TRUE, cor.analysis=TRUE,
stop("Number of columns of 'Means' and covariance matrices are different.\n")
}
if (!identical(colnames(my.cov[[1]]), colnames(Means))) {
stop("The variable names are not in the same order in 'x' and 'Means'. The results are likely incorrect unless this is what you want.\n")
stop("The variable names are not in the same order in 'x' and 'Means'.
The results are likely incorrect unless this is what you want.\n")
}

## Sampling covariance matrices of the means: covariance matrices/n
## NA are replaced with 10^5
acov_mean <- mapply(function(x, y) {
out <- x/y
out[is.na(out)] <- 1e10
out},
my.cov, n, SIMPLIFY=FALSE)
acov_mean <- mapply(function(x, y) {x/y}, my.cov, n, SIMPLIFY=FALSE)
acov_mean <- t(sapply(acov_mean, function(x) vech(x)))

## Variable names of p (sampling covariance matrix of the means
pCovNames <- matrix(paste("M(",
pCovNames <- matrix(paste("C(",
outer(obslabels, obslabels, paste, sep = " "),
")", sep=""),
nrow=length(obslabels), ncol=length(obslabels))
Expand All @@ -80,12 +96,22 @@ Cor2DataFrame <- function(x, n, v.na.replace=TRUE, cor.analysis=TRUE,
rownames(acov_mean) <- make.names(rownames(acov_mean), unique=TRUE)
}

list(data=cbind(data, Means, acov_mean), n=n, obslabels=obslabels,
ylabels=colnames(my.df), vlabels=colnames(acovR),
Meanvlabels=pCovNames)
out <- list(data=cbind(data, Means, acov_mean), n=n, obslabels=obslabels,
ylabels=colnames(my.df), vlabels=colnames(acovR),
vMlabels=pCovNames, VyMlabels=NULL)
} else {
## Without the means
list(data=data, n=n, obslabels=obslabels, ylabels=colnames(my.df),
vlabels=colnames(acovR))
out <- list(data=data, n=n, obslabels=obslabels, ylabels=colnames(my.df),
vlabels=colnames(acovR), VyMlabels=NULL)
}

## obslabels: labels of the means (Means) and dimnames in the
## correlation/covariance matrices (Cov)
## ylabels: vech(Cov) generated from list2matrix()
## vlabels: Acov of vech(Cov) generated from asyCov()
## Mlabels: labels of the means (not included as they are identical to obslabels)
## vMlabels: Acov of Means
## VyMlabels: Acov of Cov and Means (not included as Cov and Means are independent)

out
}
14 changes: 10 additions & 4 deletions R/create.mxModel.R
Original file line number Diff line number Diff line change
Expand Up @@ -157,12 +157,10 @@ create.mxModel <- function(model.name="mxModel", RAM=NULL, data=NULL,
mx.model <- mxModel(mx.model, M$mxalgebra, M$parameters, M$list)
}

mx.model <- mxModel(mx.model, Fmatrix, Id, Id_A, expCov, expMean,
mxCI(c("Amatrix", "Smatrix", "Mmatrix")))
mx.model <- mxModel(mx.model, Fmatrix, Id, Id_A, expCov, expMean)
} else {
## No mean structure
mx.model <- mxModel(mx.model, Fmatrix, Id, Id_A, expCov,
mxCI(c("Amatrix", "Smatrix")))
mx.model <- mxModel(mx.model, Fmatrix, Id, Id_A, expCov)
}

## Add additional arguments to mxModel
Expand All @@ -172,6 +170,14 @@ create.mxModel <- function(model.name="mxModel", RAM=NULL, data=NULL,
}
}

## New parameter labels including those in constraints
new.para.labels <- unique(c(A, S, M))
## Get the variable names
new.para.labels <- all.vars(parse(text=new.para.labels))
## Drop the definition variables
new.para.labels <- new.para.labels[!grepl("data.", new.para.labels)]
mx.model <- mxModel(mx.model, mxCI(new.para.labels))

## A list of mxalgebras required SE or CI
mxalgebras.ci <- NULL

Expand Down
Loading

0 comments on commit f4f500d

Please sign in to comment.