Changelog
Source:NEWS.md
metaprep 0.4.1
-
rma_mv_helper()andrma_uni_helper()accept a formula foryiagain. metafor reads a two-sidedyias estimates-on-the-left, moderators-on-the-right, sorma_mv_helper(ev, estimate ~ x)fits whatrma_mv_helper(ev, yi = estimate, mods = ~ x)fits, down to the coefficient names. Both help pages have documentedyias “Formula or bare column name” since the functions were written. 0.3.1’s non-finite guard assumedyievaluated to a numeric vector and calledis.finite()on it, so every formula call started failing withdefault method not implemented for type 'language'. The guards now check the two sides separately (left-hand side finite, right-hand side present on the object) and the formula is passed to metafor untouched, so the fit is exactly what it was before the guard existed rather than amods =call rebuilt by this package.estimate ~ 1, the plain pooled fit written in formula form, is covered by its own test against the bare-yifit.Supplying both a formula
yiandmodsis now an error rather than silently droppingmods, and a one-sidedyisuch as~ xis an error naming the fix instead of failing inside metafor.
metaprep 0.4.0
-
The variance-covariance matrix is now stored sparsely. A block-diagonal vcov is overwhelmingly zeros (99.88% on the largest object in real use), so this is a large win: 27.5 MB becomes 0.3 MB, and
metafor::rma.mv()runs roughly 7x faster because it does not densify internally. Verified against 115estimates_vcovobjects: every vcov quantity, and every pooled fit on a well-conditioned object, is unchanged.get_vcov()returns the stored matrix rather than converting it, andmake_estimates_vcov()accepts either a base matrix or aMatrixand converts neither, so storage follows the data (a bootstrappedcov()is genuinely dense and would only grow if forced sparse). Sparse matrices print with.for structural zeros, which makes the block-diagonal structure easier to read. -
Breaking-ish:
Matrixmoves fromImportstoDepends, solibrary(metaprep)now attaches it. This is required rather than cosmetic:Matrixdefinesdiag()andt()as S4 generics in its own namespace instead of adding methods to the base functions, so without attachmentdiag(ev$vcov)does not take the diagonal of a sparse matrix, it errors. AttachingMatrixmasks baset,diag,det,solve, andcrossprodin your search path. Code that testedis.matrix(ev$vcov)will now getFALSE; see the “Public interface” section of?estimates_vcovfor what the object does and does not promise. Scalar element access (V[i, j]in a loop) is markedly slower on a sparse matrix, so callas.matrix()once if you are reading thousands of individual cells. - Internally, the four operations the package performs on a vcov are now storage-agnostic, so the representation cannot affect a reported number.
rma_uni_helper()takes the diagonal withMatrix::diag()rather thandiag(), which would have errored on a sparse matrix.
metaprep 0.3.1
New
?estimates_vcovhelp page documenting the object the package is built around. It had none: the central noun of the package was undocumented, so nothing said what the components are, what theidcolumn is for, which dplyr verbs keep the vcov aligned and which are refused, or what the object guarantees at construction.?metaprepis also new, giving the four-step workflow and the two silent failures the package refuses to guess about.?estimates_vcovgains a “Public interface” section settling what callers may rely on.estimatesandvcovare public: read them asev$estimates/ev$vcovor through [get_estimates_df()] / [get_vcov()], whichever suits, and both will keep working. What is guaranteed aboutvcovis its content and shape (square, symmetric, finite, one row and column per estimate in the same order,dimnamesequal toid), not its storage class, so ordinary matrix operations are the supported way to use it andis.matrix()is not.row_mapis documented as internal, since the verbs do not agree on what its “parent” means:filter()and the filtering joins set it to positions within the object they were handed whilearrange()composes it through. Useidfor a stable per-estimate label.The S3 methods are reachable by name.
?filter.estimates_vcov,?print.estimates_vcov,?nest_by.estimates_vcovand the rest previously returned “no documentation”: thedplyr-methodspage carried no aliases, so a caller who knew a method’s name could not find its page.dplyr-methodsgains runnable examples, documented arguments, and a@returnsection. It is the page that carries themutate(estimate = -estimate)desync warning and it had nothing runnable beside the prose. The examples now show the trap and its fix on the one entry where it is visible, the within-study covariance, using a partial sign flip so the covariance changes sign.@familytags group the exports intoestimates_vcov objects,component accessors, andmeta-analysis wrappers, so every page now generates a See Also block pointing at its siblings. There were none before, across ten exports.prep_fit()gains an explicit@seealsoto the same effect.New examples use base
lm()rather thanrandomizrplusestimatr, so they run without any suggested package installed.rma_uni_helper()no longer discards covariances silently.rma.uni()takes only the variances, so calling it on an object whose vcov has nonzero off-diagonals throws away the dependence the package exists to carry and returns a standard error that is too small: on a five-estimate two-study object, 0.100 againstrma_mv_helper()’s 0.152. The docs already said to userma_mv_helper()for correlated estimates, but nothing fired at runtime. Whenviis not supplied and the vcov has nonzero off-diagonal entries,rma_uni_helper()now warns (class"metaprep_discarded_covariance"), names how many covariances were dropped, and points atrma_mv_helper(). Supplyingviexplicitly silences it and returns an identical fit, which is the way to say the univariate fit is what you meant. Objects with no covariances (the ordinary univariate case) are unaffected.rma_mv_helper()andrma_uni_helper()now error when an estimate entering the pool isNA,NaN, or infinite.metafordrops such rows with a warning and returns a fit whosekis smaller than the object, so anything joining a per-estimate quantity back onto the estimates (weights(),resid()) silently misaligns. The error names the count and the affectedids. This is the mirror of the non-finitevcovguard added in 0.2.x, and it follows the same reasoning: an estimate that cannot carry its own weight must not enter a pooled fit silently, and which estimates to drop is the analyst’s call. Verified against 115estimates_vcovobjects across the meta-reanalysis projects, none of which has a non-finite estimate, so no existing pipeline changes.Fourteen error and warning messages were silently dropping their guidance bullet.
rlang::abort(msg, "i" = hint)passes the hint into..., where rlang stores it as a condition field and never prints it; the bullets only render when they are part of the message vector, asrlang::abort(c(msg, "i" = hint)). Soas_estimates_vcov(some_data_frame)reported only “Input must contain list-columns namedtidy_objandvcov_obj.” and swallowed “Did you pass the result ofprep_fit()?”, which is the hint a first-time caller most needs. All fourteen now print their bullet: the four “did you passprep_fit()output” hints, the four dimension and squareness reports, the three missing-package install lines,get_glance_df()’s pointer to extract glance before building the object, andprep_fit()’s missing-tidy()/glance()/vcov()-method hints. A newtest-error-messages.Rasserts on the hint text rather than the headline, so the defect class cannot return silently.The vignette’s bootstrap section pooled with
random = ~ 1 | studywhere every other chunk usesrandom = ~ 1 | id, so the one place the reader meets a combined object silently switched to a different model (a study-level intercept over five levels rather than an estimate-level random effect over eight, moving tau^2 from 0.006 to 0.020 and the pooled estimate from 0.223 to 0.238). Worse, the two bootstrapped rows are one study sharing subjects, and~ 1 | studyentered them as two independent studies. Now~ 1 | idthroughout.
metaprep 0.3.0
-
Breaking:
estimates_vcov_from_pieces()is renamedmake_estimates_vcov(). No deprecated alias is kept, since the package has not been released. Rename call sites; the arguments and behavior are unchanged. -
make_estimates_vcov()is documented as the entry point for estimates whose covariances do not come from a single regression – most often experiments run on overlapping samples, where the covariance between their estimates comes from bootstrapping the design and takingcov()of the replicate estimates. Previously it was described only as a way to recombine the output ofget_estimates_df()andget_vcov(), which undersold it. The docs now state that the vcov is matched to the estimates by position and that any dimnames on the matrix are discarded, and recommend supplyingstd.errorsorescale_estimates_vcov()has standard errors to rescale. The vignette gains a “Correlated estimates with no single regression” section working the overlapping-samples bootstrap end to end, throughbind_estimates_vcov()andrma_mv_helper().
metaprep 0.2.3
-
prep_fit()’stermargument now accepts tidyselect expressions matched against the model’s term names, e.g.prep_fit(fit, starts_with("Z_party")), so callers no longer hand-build a coefficient-name vector withgrep(..., names(coef(fit))). A treatment’s main effect can be taken while dropping its interactions with tidyselect’s own set algebra, e.g.matches("^Z_treated$")orstarts_with("Z_treated") & !contains(":"). A character vector still works exactly as before (exact names, or regex withmatch = "regex").
metaprep 0.2.2
- New
rescale_estimates_vcov()sign-flips or rescales the estimates of anestimates_vcovobject and updates the vcov to match (diag(s) V diag(s)), keeping the object consistent. This is the correct way to flip signs (including a partial flip of some arms) or change units; the dplyr methods keep the vcov row-aligned but never transform it, somutate(estimate = -estimate)alone would leave the vcov inconsistent. Thedplyr-methodsdocs now note this.
metaprep 0.2.1
- The
clusterargument ofrma_mv_helper()andrma_uni_helper()now accepts a bare column name, a string-named column via.data[[var]], or an external vector (previously only a bare column name worked). It is captured withrlang::enquo(), so it composes inside wrapper functions that pass the clustering variable programmatically.
metaprep 0.2.0
-
rma_mv_helper()andrma_uni_helper()gain aclusterargument (a bare column name evaluated in the estimates, likeyi) and aclubSandwichargument. Whenclusteris supplied the fit is wrapped in [metafor::robust()], sorma_mv_helper(ev, yi = estimate, random = ~ 1 | id, cluster = study)returns CR2 cluster-robust standard errors in one step. Defaults are unchanged (cluster = NULLreturns the ordinary fit). - New
bind_estimates_vcov()combines two or moreestimates_vcovobjects into one, stacking the estimates and assembling a block-diagonal vcov (zero covariance between objects), withidrenumbered across the result. -
as_estimates_vcov()andestimates_vcov_from_pieces()now repair floating-point asymmetry in the vcov and error on asymmetry beyond a relative tolerance, which would indicate a malformed (non-covariance) matrix. -
rma_mv_helper()andrma_uni_helper()now error if amodsformula references a column that is not on theestimates_vcovobject, so a moderator that never made it onto the object fails loudly instead of silently producing an empty meta-regression. The vignette gains sections on cluster-robust standard errors and meta-regression.
metaprep 0.1.0
- First release.
-
prep_fit()extracts tidy estimates, aglance()summary, and the relevant variance-covariance submatrix from a fitted model, with exact or regex term matching and multivariate-model handling. -
as_estimates_vcov()andestimates_vcov_from_pieces()build anestimates_vcovobject that keeps coefficient estimates and their block-diagonal vcov matrix synchronized. - dplyr methods (
filter(),slice(),arrange(),mutate(),select(),rename(),nest_by(), and the join verbs) operate onestimates_vcovobjects while keeping the vcov matrix in sync. -
get_estimates_df(),get_glance_df(), andget_vcov()pull the components back out of either a prepped-fits tibble or anestimates_vcovobject. -
rma_mv_helper()andrma_uni_helper()wrapmetafor::rma.mv()andmetafor::rma.uni(), reading the estimates and vcov directly from anestimates_vcovobject.