# The metafor Package

A Meta-Analysis Package for R

updates

## Package Updates

On this page, you can find a description of the (recent) updates to the metafor package. Older updates are archived here.

### Changes in Version 1.9-9 (2016-09-25)

• started to use git as version control system, GitHub to host the repository (https://github.com/wviechtb/metafor) for the development version of the package, Travis CI as continuous integration service (https://travis-ci.org/wviechtb/metafor), and Codecov for automated code coverage reporting (https://codecov.io/github/wviechtb/metafor)
• argument knha in rma.uni() and argument tdist in rma.glmm() and rma.mv() are now superseded by argument test in all three functions; for backwards compatibility, the knha and tdist arguments still work, but are no longer documented
• rma(yi, vi, weights=1, test="knha") now yields the same results as rma(yi, vi, weighted=FALSE, test="knha") (but use of the Knapp and Hartung method in the context of an unweighted analysis remains an experimental feature)
• one can now pass an escalc object directly to rma.uni(), which then tries to automatically determine the yi and vi variables in the data frame (thanks to Christian Röver for the suggestion)
• escalc() can now also be used to convert a regular data frame to an escalc object
• for measure="UCOR", the exact bias-correction is now used (instead of the approximation); when vtype="UB", the exact equation is now used to compute the unbiased estimate of the variance of the bias-corrected correlation coefficient; hence gsl is now a suggested package (needed to compute the hypergeometric function) and is loaded when required
• cooks.distance() now also works with rma.mv objects; and since model fitting can take some time, an option to show a progress bar has been added
• fixed an issue with robust.rma.mv() throwing errors when the model was fitted with sparse=TRUE
• fixed an error with robust.rma.mv() when the model was fitted with user-defined weights (or a user-defined weight matrix)
• added ranef() for extracting the BLUPs of the random effects (only for rma.uni objects at the moment)
• reverted back to the pre-1.1-0 way of computing p-values for individual coefficients in permutest.rma.uni(), that is, the p-value is computed with mean(abs(z_perm) >= abs(z_obs) - tol) (where tol is a numerical tolerance)
• permutest.rma.uni() gains permci argument, which can be used to obtain permutation-based CIs of the model coefficients (note that this is computationally very demanding and may take a long time to complete)
• rma.glmm() continues to work even when the saturated model cannot be fitted (although the tests for heterogeneity are not available then)
• rma.glmm() now allows control over the arguments used for method.args (via control=list(hessianCtrl=list(...))) passed to hessian() (from the numDeriv package) when using model="CM.EL" and measure="OR"
• in rma.glmm(), default method.args value for r passed to hessian() has been increased to 16 (while this slows things down a bit, this appears to improve the accuracy of the numerical approximation to the Hessian, especially when tau^2 is close to 0)
• the various forest() and addpoly() functions now have a new argument called width, which provides manual control over the width of the annotation columns; this is useful when creating complex forest plots with a monospaced font and we want to ensure that all annotations are properly lined up at the decimal point
• the annotations created by the various forest() and addpoly() functions are now a bit more compact by default
• more flexible efac argument in the various forest() functions
• trailing zeros in the axis labels are now dropped in forest and funnel plots by default; but trailing zeros can be retained by specifying a numeric (and not an integer) value for the digits argument
• added funnel.default(), which directly takes as input a vector with the observed effect sizes or outcomes and the corresponding sampling variances, standard errors, and/or sample sizes
• added plot.profile.rma(), a plot method for objects returned by the profile.rma.uni() and profile.rma.mv() functions
• simplified baujat.rma.uni(), baujat.rma.mh(), and baujat.rma.peto() to baujat.rma(), which now handles objects of class rma.uni, rma.mh, and rma.peto
• baujat.rma() gains argument symbol for more control over the plotting symbol
• labbe() gains a grid argument
• more logical placement of labels in qqnorm.rma.uni(), qqnorm.rma.mh(), and qqnorm.rma.peto() functions (and more control thereof)
• qqnorm.rma.uni() gains lty argument
• added gosh.rma() and plot.gosh.rma() for creating GOSH (i.e., graphical display of study heterogeneity) plots based on Olkin et al. (2012)
• in the (rare) case where all observed outcomes are exactly equal to each other, test="knha" (i.e., knha=TRUE) in rma() now leads to more appropriate results
• updated datasets so those containing precomputed effect size estimates or observed outcomes are already declared to be escalc objects
• added new datasets (dat.egger2001 and dat.li2007) on the effectiveness of intravenous magnesium in acute myocardial infarction
• methods package is now under Depends (in addition to Matrix), so that rma.mv(..., sparse=TRUE) always works, even under Rscript
• some general code cleanup
• added more tests (and used a more consistent naming scheme for tests)

### Changes in Version 1.9-8 (2015-05-28)

• due to more stringent package testing, it is increasingly difficult to ensure that the package passes all checks on older versions of R; from now on, the package will therefore require, and be checked under, only the current (and the development) version of R
• added graphics, grDevices, and methods to Imports (due to recent change in how CRAN checks packages)
• the struct argument for rma.mv() now also allows for "ID" and "DIAG", which are identical to the "CS" and "HCS" structures, but with the correlation parameter fixed to 0
• added robust() for (cluster) robust tests and confidence intervals for rma.uni and rma.mv models (this uses a robust sandwich-type estimator of the variance-covariance matrix of the fixed effects along the lines of the Eicker-Huber-White method)
• confint() now works for models fitted with the rma.mv() function; for variance and correlation parameters, the function provides profile likelihood confidence intervals; the output generated by the confint() function has been adjusted in general to make the formatting more consistent across the different model types
• for objects of class rma.mv, profile() now provides profile plots for all (non-fixed) variance and correlation components of the model when no component is specified by the user (via the sigma2, tau2, rho, gamma2, or phi arguments)
• for measure="MD" and measure="ROM", one can now choose between vtype="LS" (the default) and vtype="HO"; the former computes the sampling variances without assuming homoscedasticity, while the latter assumes homoscedasticity
• multiple model objects can now be passed to the fitstats(), AIC(), and BIC() functions
• check for duplicates in the slab argument is now done *after* any subsetting is done (as suggested by Michael Dewey)
• rma.glmm() now again works when using add=0, in which case some of the observed outcomes (e.g., log odds or log odds ratios) may be NA
• when using rma.glmm() with model="CM.EL", the saturated model (used to compute the Wald-type and likelihood ratio tests for the presence of (residual) heterogeneity) often fails to converge; the function now continues to run (instead of stopping with an error) and simply omits the test results from the output
• when using rma.glmm() with model="CM.EL" and inversion of the Hessian fails via the Choleski factorization, the function now makes another attempt via the QR decomposition (even when this works, a warning is issued)
• for rma.glmm(), BIC and AICc values were switched around; corrected
• more use of suppressWarnings() is made when functions repeatedly need to fit the same model, such as cumul(), influence(), and profile(); that way, one does not get inundated with the same warning(s)
• some (overdue) updates to the documentation

### Changes in Version 1.9-7 (2015-05-21)

• default optimizer for rma.mv() changed to nlminb() (instead of optim() with "Nelder-Mead"); extensive testing indicated that nlminb() (and also optim() with "BFGS") is typically quicker and more robust; note that this is in principle a non-backwards compatible change, but really a necessary one; and you can always revert to the old behavior with control=list(optimizer="optim", optmethod="Nelder-Mead")
• all tests have been updated in accordance with the recommended syntax of the testthat package; for example, expect_equivalent(x,y) is used instead of test_that(x, is_equivalent_to(y))
• changed a few is_identical_to() comparisons to expect_equivalent() ones (that failed on Sparc Solaris)

### Changes in Version 1.9-6 (2015-05-07)

• funnel() now works again for rma.glmm objects (note to self: quit breaking things that work!)
• rma.glmm() will now only issue a warning (and not an error) when the Hessian for the saturated model cannot be inverted (which is needed to compute the Wald-type test for heterogeneity, so the test statistic is then simply set to NA)
• rma.mv() now allows for two terms of the form ~ inner | outer; the variance components corresponding to such a structure are called gamma2 and correlations are called phi; other functions that work with objects of class rma.mv have been updated accordingly
• rma.mv() now provides (even) more optimizer choices: nlm() from the stats package, hjk() and nmk() from the dfoptim package, and ucminf() from the ucminf package; choose the desired optimizer via the control argument (e.g., control=list(optimizer="nlm"))
• profile.rma.uni() and profile.rma.mv() now can do parallel processing (which is especially relevant for rma.mv objects, where profiling is crucial and model fitting can be slow)
• the various confint() functions now have a transf argument (to apply some kind of transformation to the model coefficients and confidence interval bounds); coefficients and bounds for objects of class rma.mh and rma.peto are no longer automatically transformed
• the various forest() functions no longer enforce that the actual x-axis limits (alim) encompass the observed outcomes to be plotted; also, outcomes below or above the actual x-axis limits are no longer shown
• the various forest() functions now provide control over the horizontal lines (at the top/bottom) that are automatically added to the plot via the lty argument (this also allows for removing them); also, the vertical reference line is now placed *behind* the points/CIs
• forest.default() now has argument col which can be used to specify the color(s) to be used for drawing the study labels, points, CIs, and annotations
• the efac argument for forest.rma() now also allows two values, the first for the arrows and CI limits, the second for summary estimates
• corrected some axis labels in various plots when measure="PLO"
• axes in labbe() plots now have "(Group 1)" and "(Group 2)" added by default
• anova.rma() gains argument L for specifying linear combinations of the coefficients in the model that should be tested to be zero
• in case removal of a row of data would lead to one or more inestimable model coefficients, baujat(), cooks.distance(), dfbetas(), influence(), and rstudent() could fail for rma.uni objects; such cases are now handled properly
• for models with moderators, the predict() function now shows the study labels when they have been specified by the user (and newmods is not used)
• if there is only one fixed effect (model coefficient) in the model, the print.infl.rma.uni() function now shows the DFBETAS values with the other case diagnostics in a single table (for easier inspection); if there is more than one fixed effect, a separate table is still used for the DFBETAS values (with one column for each coefficient)
• added measure="SMCRH" to the escalc() function for the standardized mean change using raw score standardization with heteroscedastic population variances at the two measurement occasions
• added measure="ROMC" to the escalc() function for the (log transformed) ratio of means (response ratio) when the means reflect two measurement occasions (e.g., for a single group of people) and hence are correlated
• added own function for computing/estimating the tetrachoric correlation coefficient (for measure="RTET"); package therefore no longer suggests polycor but now suggest mvtnorm (which is loaded as needed)
• element fill returned by trimfill.rma.uni() is now a logical vector (instead of a 0/1 dummy variable)
• print.list.rma() now also returns the printed results invisibly as a data frame
• added a new dataset (dat.senn2013) as another illustration of a network meta-analysis
• metafor now depends on at least version 3.1.0 of R

### Changes in Version 1.9-5 (2014-11-24)

• moved the stats and Matrix packages from Depends to Imports; as a result, had to add utils to Imports; moved the Formula package from Depends to Suggests
• added update.rma() function (for updating/refitting a model); model objects also now store and keep the call
• the vcov() function now also extracts the marginal variance-covariance matrix of the observed effect sizes or outcomes from a fitted model (of class rma.uni or rma.mv)
• rma.mv() now makes use of the Cholesky decomposition when there is a random = ~ inner | outer formula and struct="UN"; this is numerically more stable than the old approach that avoided non-positive definite solutions by forcing the log-likelihood to be -Inf in those cases; the old behavior can be restored with control = list(cholesky=FALSE)
• rma.mv() now requires the inner variable in an ~ inner | outer formula to be a factor or character variable (except when struct is "AR" or "HAR"); use ~ factor(inner) | outer in case it isn't
• anova.rma.uni() function changed to anova.rma() that works now for both rma.uni and rma.mv objects
• the profile.rma.mv() function now omits the number of the variance or correlation component from the plot title and x-axis label when the model only includes one of the respective parameters
• profile() functions now pass on the ... argument also to the title() function used to create the figure titles (esp. relevant when using the cex.main argument)
• the drop00 argument of the rma.mh() and rma.peto() functions now also accepts a vector with two logicals, the first applies when calculating the observed outcomes, the second when applying the Mantel-Haenszel or Peto's method
• weights.rma.uni() now shows the correct weights when weighted=FALSE
• argument showweight renamed to showweights in the forest.default() and forest.rma() functions (more consistent with the naming of the various weights() functions)
• added model.matrix.rma() function (to extract the model matrix from objects of class rma)
• funnel() and radial() now (invisibly) return data frames with the coordinates of the points that were drawn (may be useful for manual labeling of points in the plots)
• permutest.rma.uni() function now uses a numerical tolerance when making comparisons (>= or ⇐) between an observed test statistic and the test statistic under the permuted data; when using random permutations, the function now ensures that the very first permutation correspond to the original data
• corrected some missing/redundant row/column labels in some output
• most require() calls replaced with requireNamespace() to avoid altering the search path (hopefully this won't break stuff ...)
• some non-visible changes including more use of some (non-exported) helper functions for common tasks
• dataset dat.collins91985a updated (including all reported outcomes and some more information about the various trials)
• oh, and guess what? I updated the documentation ...

### Changes in Version 1.9-4 (2014-07-30)

• added method="GENQ" to rma.uni() for the generalized Q-statistic estimator of tau^2, which allows for used-defined weights (note: the DL and HE estimators are just special cases of this method)
• when the model was fitted with method="GENQ", then confint() will now use the generalized Q-statistic method to construct the corresponding confidence interval for tau^2 (thanks to Dan Jackson for the code); the iterative method used to obtain the CI makes use of Farebrother's algorithm as implemented in the CompQuadForm package
• slight improvements in how the rma.uni() function handles non-positive sampling variances
• rma.uni(), rma.mv(), and rma.glmm() now try to detect and remove any redundant predictors before the model fitting; therefore, if there are exact linear relationships among the predictor variables (i.e., perfect multicollinearity), terms are removed to obtain a set of predictors that is no longer perfectly multicollinear (a warning is issued when this happens); note that the order of how the variables are specified in the model formula can influence which terms are removed
• the last update introduced an error in how hat values were computed when the model was fitted with the rma() function using the Knapp & Hartung method (i.e., when knha=TRUE); this has been fixed
• regtest() no longer works (for now) with rma.mv objects (it wasn't meant to in the first place); if you want to run something along the same lines, just consider adding some measure of the precision of the observed outcomes (e.g., their standard errors) as a predictor to the model
• more optimizers are now available for the rma.mv() function via the nloptr package by setting control = list(optimizer="nloptr"); when using this optimizer, the default is to use the BOBYQA implementation from that package with a relative convergence criterion of 1e-8 on the function value (see documentation on how to change these defaults)
• predict.rma() function now works for rma.mv objects with multiple tau^2 values even if the user specifies the newmods argument but not the tau2.levels argument (but a warning is issued and the credibility/prediction intervals are not computed)
• argument var.names now works properly in escalc() when the user has not made use of the data argument (thanks to Jarrett Byrnes for bringing this to my attention)
• added plot() function for cumulative random-effects models results as obtained with the cumul.rma.uni() function; the plot shows the model estimate on the x-axis and the corresponding tau^2 estimate on the y-axis in the cumulative order of the results
• fixed the omitted offset term in the underlying model fitted by the rma.glmm() function when method="ML", measure="IRR", and model="UM.FS", that is, when fitting a mixed-effects Poisson regression model with fixed study effects to two-group event count data (thanks to Peter Konings for pointing out this error)
• added two new datasets (dat.bourassa1996, dat.riley2003)
• added function replmiss() (just a useful helper function)
• package now uses LazyData: TRUE
• some improvements to the documentation (do I still need to mention this every time?)

### Changes in Version 1.9-3 (2014-05-05)

• some minor tweaks to rma.uni() that should be user transparent
• rma.uni() now has a weights argument, allowing the user to specify arbitrary user-defined weights; all functions affected by this have been updated accordingly
• better handling of mismatched length of yi and ni vectors in rma.uni() and rma.mv() functions
• subsetting is now handled as early as possible within functions with subsetting capabilities; this avoids some (rare) cases where studies ultimately excluded by the subsetting could still affect the results
• some general tweaks to rma.mv() that should make it a bit faster
• argument V of rma.mv() now also accepts a list of var-cov matrices for the observed effects or outcomes; from the list elements, the full (block diagonal) var-cov matrix V is then automatically constructed
• rma.mv() now has a new argument W allowing the user to specify arbitrary user-defined weights or an arbitrary weight matrix
• rma.mv() now has a new argument sparse; by setting this to true, the function uses sparse matrix objects to the extent possible; this can speed up model fitting substantially for certain models (hence, the metafor package now depends on the Matrix package)
• rma.mv() now allows for struct="AR" and struct="HAR", to fit models with (heteroscedastic) autoregressive (AR1) structures among the true effects (useful for meta-analyses of studies reporting outcomes at multiple time points)
• rma.mv() now has a new argument Rscale which can be used to control how matrices specified via the R argument are scaled (see docs for more details)
• rma.mv() now only checks for missing values in the rows of the lower triangular part of the V matrix (including the diagonal); this way, if Vi = matrix(c(.5,NA,NA,NA), nrow=2, ncol=2) is the var-cov matrix of the sampling errors for a particular study with two outcomes, then only the second row/column needs to be removed before the model fitting (and not the entire study)
• added five new datasets (dat.begg1989, dat.ishak2007, dat.fine1993, dat.konstantopoulos2011, and dat.hasselblad1998) to provide further illustrations of the use of the rma.mv() function (for meta-analyses combining controlled and uncontrolled studies, for meta-analyses of longitudinal studies, for multilevel meta-analyses, and for network meta-analyses / mixed treatment comparison meta-analyses)
• added rstandard.rma.mv() function to compute standardized residuals for models fitted with the rma.mv() function (rstudent.rma.mv() to be added at a later point); also added hatvalues.rma.mv() for computing the hat values and weights.rma.uni() for computing the weights (i.e., the diagonal elements of the weight matrix)
• the various weights() functions now have a new argument type to indicate whether only the diagonal elements of the weight matrix (default) or the entire weight matrix should be returned
• the various hatvalues() functions now have a new argument type to indicate whether only the diagonal elements of the hat matrix (default) or the entire hat matrix should be returned
• predict.rma() function now works properly for rma.mv objects (also has a new argument tau2.levels to specify, where applicable, the levels of the inner factor when computing credibility/prediction intervals)
• forest.rma() function now provides a bit more control over the color of the summary polygon and is now compatible with rma.mv objects; also, has a new argument lty, which provides more control over the line type for the individual CIs and the credibility interval
• addpoly.default() and addpoly.rma() now have a border argument (for consistency with the forest.rma() function); addpoly.rma() now yields the correct CI bounds when the model was fitted with knha=TRUE
• forest.cumul.rma() now provides the correct CI bounds when the models were fitted with the Knapp & Hartung method (i.e., when knha=TRUE in the original rma() function call)
• the various forest() functions now return information about the chosen values for arguments xlim, alim, at, ylim, rows, cex, cex.lab, and cex.axis invisibly (useful for tweaking the default values); thanks to Michael Dewey for the suggestion
• the various forest() functions now have a new argument, clim, to set limits for the confidence/credibility/prediction interval bounds
• cumul.mh() and cumul.peto() now get the order of the studies right when there are missing values in the data
• the transf argument of leave1out.rma.mh(), leave1out.rma.peto(), cumul.rma.mh(), and cumul.rma.peto() should now be used to specify the actual function for the transformation (the former behavior of setting this argument to TRUE to exponentiate log RRs, log ORs, or log IRRs still works for back-compatibility); this is more consistent with how the cumul.rma.uni() and leave1out.rma.uni() functions work and is also more flexible
• added bldiag() function to construct a block diagonal matrix from (a list of) matrices (may be needed to construct the V matrix when using the rma.mv() function); bdiag() function from the Matrix package does the same thing, but creates sparse matrix objects
• profile.rma.mv() now has a startmethod argument; by setting this to "prev", successive model fits are started at the parameter estimates from the previous model fit; this may speed things up a bit; also, the method for automatically choosing the xlim values has been changed
• slight improvement to profile.rma.mv() function, which would throw an error if the last model fit did not converge
• added a new dataset (dat.linde2005) for replication of the analyses in Viechtbauer (2007)
• added a new dataset (dat.molloy2014) for illustrating the meta-analysis of (r-to-z transformed) correlation coefficients
• added a new dataset (dat.gibson2002) to illustrate the combined analysis of standardized mean differences and probit transformed risk differences
• computations in weights.mh() slightly changed to prevent integer overflows for large counts
• unnecessary warnings in transf.ipft.hm() are now suppressed (cases that raised those warnings were already handled correctly)
• in predict(), blup(), cumul(), and leave1out(), when using the transf argument, the standard errors (which are NA) are no longer shown in the output
• argument slab in various functions will now also accept non-unique study labels; make.unique() is used as needed to make them unique
• vignettes("metafor") and vignettes("metafor_diagram") work again (yes, I know they are not true vignettes in the strict sense, but I think they should show up on the CRAN website for the package and using a minimal valid Sweave document that is recognized by the R build system makes that happen)
• escalc() and its summary() method now keep better track when the data frame contains multiple columns with outcome or effect size values (and corresponding sampling variances) for print formatting; also simplified the class structure a bit (and hence, print.summary.escalc() removed)
• summary.escalc() has a new argument H0 to specify the value of the outcome under the null hypothesis for computing the test statistics
• added measures "OR2DN" and "D2ORN" to escalc() for transforming log odds ratios to standardized mean differences and vice-versa, based on the method of Cox & Snell (1989), which assumes normally distributed response variables within the two groups before the dichotomization
• permutest.rma.uni() function now catches an error when the number of permutations requested is too large (for R to even create the objects to store the results in) and produces a proper error message
• funnel.rma() function now allows the yaxis argument to be set to "wi" so that the actual weights (in %) are placed on the y-axis (useful when arbitrary user-defined have been specified)
• for rma.glmm(), the control argument optCtrl is now used for passing control arguments to all of the optimizers (hence, control arguments nlminbCtrl and minqaCtrl are now defunct)
• rma.glmm() should not throw an error anymore when including only a single moderator/predictor in the model
• predict.rma() now returns an object of class list.rma (therefore, function print.predict.rma() has been removed)
• for rma.list objects, added [, head(), and tail() methods
• automated testing using the testthat package (still many more tests to add, but finally made a start on this)
• encoding changed to UTF-8 (to use 'foreign characters' in the docs and to make the HTML help files look a bit nicer)
• guess what? some improvements to the documentation! (also combined some of the help files to reduce the size of the manual a bit; and yes, it's still way too big)

### Changes in Older Versions

Older updates are archived here.

updates.txt · Last modified: 2016/09/25 18:14 by Wolfgang Viechtbauer