├── .Rbuildignore ├── .gitignore ├── .travis.yml ├── DESCRIPTION ├── LICENSE ├── LICENSE.md ├── NAMESPACE ├── R ├── add.R ├── augment.R ├── data.R ├── geom_funnel.R ├── glance.R ├── influence.R ├── meta_analysis.R ├── quick_plots.R ├── text_table.R ├── themes.R ├── tidy.R ├── utils-pipe.R └── utils.R ├── README.Rmd ├── README.md ├── appveyor.yml ├── data-raw └── iud_cxca.csv ├── data └── iud_cxca.rda ├── man ├── add.Rd ├── add_meta.Rd ├── augmenters.Rd ├── cumulative.Rd ├── figures │ ├── README-unnamed-chunk-1-1.png │ ├── README-unnamed-chunk-6-1.png │ └── README-unnamed-chunk-7-1.png ├── geom_funnel.Rd ├── glance.rma.uni.Rd ├── iud_cxca.Rd ├── lock_order.Rd ├── log_scales.Rd ├── meta_analysis.Rd ├── metathemes.Rd ├── pipe.Rd ├── pull_meta.Rd ├── pull_summary.Rd ├── quickplots.Rd ├── sensitivity.Rd ├── sub2summary.Rd ├── text_table.Rd └── tidiers.Rd └── tidymeta.Rproj /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^.*\.Rproj$ 2 | ^\.Rproj\.user$ 3 | ^README\.Rmd$ 4 | ^data-raw$ 5 | ^LICENSE\.md$ 6 | ^\.travis\.yml$ 7 | ^appveyor\.yml$ 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | .Ruserdata 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # R for travis: see documentation at https://docs.travis-ci.com/user/languages/r 2 | 3 | language: R 4 | sudo: false 5 | cache: packages 6 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: tidymeta 2 | Type: Package 3 | Title: Tidy and Plot Meta Analyses 4 | Version: 0.1.0.9000 5 | Authors@R: person("Malcolm", "Barrett", 6 | email = "malcolmbarrett@gmail.com", 7 | role = c("aut", "cre")) 8 | Maintainer: Malcolm Barrett 9 | Description: Tidy and plot meta-analyses from meta-analytic tools in R. 10 | Currently supports `metafor`. `tidymeta` makes it easy to work with 11 | meta-analyses in a tidy and consistent manner. In addition to working with 12 | results, `tidymeta` also includes `ggplot2` geoms and common data 13 | visualizations for meta-analyses, such as forest plots, funnel plots, 14 | and influence plots. 15 | Depends: 16 | R (>= 2.10) 17 | License: MIT + file LICENSE 18 | Encoding: UTF-8 19 | LazyData: true 20 | Roxygen: list(markdown = TRUE) 21 | RoxygenNote: 6.0.1.9000 22 | Imports: 23 | magrittr, 24 | metafor, 25 | broom, 26 | dplyr, 27 | ggplot2 (>= 2.2.1.9000), 28 | purrr, 29 | forcats, 30 | rlang (>= 0.2.0.9001), 31 | stringr, 32 | tibble, 33 | scales, 34 | tidyr, 35 | patchwork 36 | Remotes: thomasp85/patchwork, 37 | tidyverse/ggplot2, 38 | tidyverse/rlang 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | YEAR: 2018 2 | COPYRIGHT HOLDER: Malcolm Barrett 3 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # MIT License 2 | 3 | Copyright (c) 2018 Malcolm Barrett 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export("%>%") 4 | export(add_blups) 5 | export(add_h2) 6 | export(add_i2) 7 | export(add_meta) 8 | export(add_residuals) 9 | export(add_rstandard) 10 | export(add_tau2) 11 | export(add_weights) 12 | export(augment.rma.uni) 13 | export(cumulative) 14 | export(cumulative_plot) 15 | export(forest_plot) 16 | export(funnel_plot) 17 | export(geom_funnel) 18 | export(glance.rma.uni) 19 | export(influence_plot) 20 | export(lock_order) 21 | export(meta_analysis) 22 | export(pull_meta) 23 | export(pull_summary) 24 | export(scale_x_log) 25 | export(scale_y_log) 26 | export(sensitivity) 27 | export(sub2summary) 28 | export(text_table) 29 | export(theme_forest) 30 | export(theme_meta) 31 | export(tidy.rma.uni) 32 | importFrom(ggplot2,"%+replace%") 33 | importFrom(magrittr,"%>%") 34 | importFrom(purrr,"%||%") 35 | importFrom(rlang,"!!!") 36 | importFrom(rlang,"!!") 37 | importFrom(tibble,tibble) 38 | -------------------------------------------------------------------------------- /R/add.R: -------------------------------------------------------------------------------- 1 | #' Add model values to a table of meta-analysis results 2 | #' 3 | #' `add_weights()` adds study weights to the model. `add_residuals()` and 4 | #' `add_rstandard()` add residuals. `add_i2()`, `add_h2()`, `add_tau2()` 5 | #' 6 | #' @param x a tidied meta-analysis 7 | #' @param .meta a meta-analysis object. If not `NULL`, then looks for a `meta` 8 | #' column in `x` containing an overall meta-analysis 9 | #' @param group a grouping variable 10 | #' @param exponentiate logical. Should the results be exponentiated? 11 | #' 12 | #' @return a `tbl` 13 | #' @export 14 | #' 15 | #' @examples 16 | #' 17 | #' library(dplyr) 18 | #' 19 | #' iud_cxca %>% 20 | #' group_by(group) %>% 21 | #' meta_analysis(, yi = lnes, sei = selnes, slab = study_name) %>% 22 | #' add_i2() 23 | #' 24 | #' @rdname add 25 | #' @name add 26 | #' 27 | #' @importFrom rlang !! 28 | add_weights <- function(x, .meta = NULL, group = NULL) { 29 | .group <- rlang::enquo(group) 30 | wts <- pull_meta(x) %>% 31 | weights() %>% 32 | tibble::enframe("study", "weight") 33 | attributes(wts$study) <- NULL 34 | x <- dplyr::left_join(x, wts, by = "study") 35 | 36 | 37 | if (!rlang::quo_is_null(.group)) { 38 | x <- x %>% 39 | dplyr::group_by(!!.group) %>% 40 | dplyr::mutate(weight = ifelse(type == "summary", 41 | sum(weight, na.rm = TRUE), weight)) %>% 42 | dplyr::ungroup() 43 | } 44 | 45 | x %>% 46 | dplyr::mutate(weight = ifelse(study == "Overall", 100.00, weight)) 47 | 48 | } 49 | 50 | #' @export 51 | #' @rdname add 52 | add_residuals <- function(x, .meta = NULL) { 53 | pull_meta(x) %>% 54 | residuals() %>% 55 | tibble::enframe("study", ".resid") %>% 56 | dplyr::left_join(x, ., by = "study") 57 | } 58 | 59 | #' @export 60 | #' @rdname add 61 | add_rstandard <- function(x, .meta = NULL) { 62 | pull_meta(x) %>% 63 | rstandard() %>% 64 | as.data.frame() %>% 65 | tibble::rownames_to_column("study") %>% 66 | dplyr::select(study, .std.resid = resid) %>% 67 | dplyr::left_join(x, ., by = "study") 68 | } 69 | 70 | #' @export 71 | #' @rdname add 72 | add_i2 <- function(x, .meta = NULL) { 73 | x %>% dplyr::mutate(i.squared = purrr::map_dbl(meta, function(.x) { 74 | if (is.null(.x)) NA_real_ else .x$I2 75 | })) 76 | } 77 | 78 | #' @export 79 | #' @rdname add 80 | add_h2 <- function(x, .meta = NULL) { 81 | x %>% dplyr::mutate(h.squared = purrr::map_dbl(meta, function(.x) { 82 | if (is.null(.x)) NA_real_ else .x$H2 83 | })) 84 | } 85 | 86 | #' @export 87 | #' @rdname add 88 | add_tau2 <- function(x, .meta = NULL) { 89 | x %>% dplyr::mutate(tau.squared = purrr::map_dbl(meta, function(.x) { 90 | if (is.null(.x)) NA_real_ else .x$tau2 91 | })) 92 | } 93 | 94 | #' #' @export 95 | #' #' @rdname add 96 | #' add_predictions <- function(x, .meta = NULL) { 97 | #' pull_meta(x) %>% 98 | #' predict() %>% 99 | #' tibble::enframe("study", "weight") %>% 100 | #' dplyr::left_join(x, ., by = "study") 101 | #' } 102 | 103 | #' @export 104 | #' @rdname add 105 | add_blups <- function(x, .meta = NULL, exponentiate = FALSE) { 106 | x <- pull_meta(x) %>% 107 | metafor::blup() %>% 108 | as.data.frame() %>% 109 | tibble::rownames_to_column("study") %>% 110 | dplyr::select(study, .fitted = pred, .se.fit = se, 111 | .pil.fit = pi.lb, .piu.fit = pi.ub) %>% 112 | dplyr::left_join(x, ., by = "study") 113 | 114 | if (exponentiate) { 115 | x <- dplyr::mutate(.fitted = exp(.fitted), 116 | .pil.fit = exp(.pil.fit), 117 | .piu.fit = exp(.piu.fit)) 118 | } 119 | 120 | x 121 | } 122 | -------------------------------------------------------------------------------- /R/augment.R: -------------------------------------------------------------------------------- 1 | #' Augment data with values from a meta-analysis model 2 | #' 3 | #' Augment the original data with model residuals, fitted values, and influence 4 | #' statistics. 5 | #' 6 | #' @param x a meta-analysis object. Currently supports `rma.uni` from the 7 | #' `metafor` package. 8 | #' @param ... additional arguments 9 | #' 10 | #' @return a `data.frame` 11 | #' @export 12 | #' 13 | #' @examples 14 | #' 15 | #' library(broom) 16 | #' library(metafor) 17 | #' rma(yi = lnes, sei = selnes, slab = study_name, data = iud_cxca) %>% 18 | #' augment() 19 | #' 20 | #' @rdname augmenters 21 | augment.rma.uni <- function(x, ...) { 22 | blup0 <- purrr::possibly(metafor::blup, NULL) 23 | residuals0 <- purrr::possibly(stats::residuals, NULL) 24 | influence0 <- purrr::possibly(stats::influence, NULL) 25 | 26 | 27 | y <- x$yi 28 | pred <- blup0(x) %>% as.data.frame() 29 | names(pred) <- c(".fitted", ".se.fit", "conf.low.fit", "conf.high.fit") 30 | res <- residuals0(x) 31 | inf <- influence0(x) 32 | inf <- cbind(as.data.frame(inf$inf), dfbetas = inf$dfbs$intrcpt) 33 | ret <- cbind(.rownames = x$slab, 34 | y, 35 | pred, 36 | .resid = res, 37 | dplyr::select(inf, .hat = hat, .cooksd = cook.d, .std.resid = rstudent, 38 | .dffits = dffits, .cov.ratio = cov.r, 39 | tau.squared.del = tau2.del, qe.del = QE.del, 40 | .weight = weight, .dfbetas = dfbetas) 41 | ) 42 | row.names(ret) <- NULL 43 | if (all(ret$.rownames == seq_along(ret$.rownames))) { 44 | ret$.rownames <- NULL 45 | } 46 | ret 47 | } 48 | -------------------------------------------------------------------------------- /R/data.R: -------------------------------------------------------------------------------- 1 | #' @importFrom tibble tibble 2 | NULL 3 | 4 | #' Meta-analysis of IUD and cervical cancer 5 | #' 6 | #' This is data from a meta-analysis of the effect of Intrauterine Device use on 7 | #' cervical cancer. Estimates are odds ratios for ever-use of IUD. 8 | #' 9 | #' @format A `tbl` with variables about both study esimates and study methods, 10 | #' including variables controlled, study design, and publication year. 11 | #' 12 | #' @source Cortessis, V. K., Barrett, M., Brown Wade, N., Enebish, T., Perrigo, 13 | #' J., Tobin, J., Zhong, C., Zink, J.,Isiaka, V., Muderspach, L., Natavio, M., 14 | #' & McKean-Cowdin, R. (2017). “Intrauterine device use and risk of cervical 15 | #' cancer: a systematic review and meta-analysis.” Obstetrics and Gynecology: 16 | #' 130 (6). 17 | "iud_cxca" 18 | -------------------------------------------------------------------------------- /R/geom_funnel.R: -------------------------------------------------------------------------------- 1 | StatFunnel <- ggplot2::ggproto("StatFunnel", ggplot2::Stat, 2 | compute_group = function(data, scales, params, ci_level = .95, 3 | log_summary = FALSE, 4 | summary_label = "Summary\nEstimate", 5 | ci_label = NULL) { 6 | 7 | if (is.null(ci_label)) ci_label <- paste0(ci_level * 100, "% CI") 8 | ci_level <- 1 - ci_level 9 | se_sign <- sign(data$y)[1] 10 | max_se <- max(abs(data$y)) 11 | summary_est <- data$summary[1] 12 | 13 | if (log_summary) summary_est <- log10(summary_est) 14 | ci_lb <- summary_est - qnorm(ci_level/2, lower.tail = FALSE) * max_se 15 | ci_ub <- summary_est + qnorm(ci_level/2, lower.tail = FALSE) * max_se 16 | 17 | ci_lines <- rbind( 18 | data.frame(x = rep(summary_est, 2), 19 | y = c(max_se, 0), 20 | linetype = summary_label, 21 | group = 1), 22 | data.frame(x = c(ci_lb, summary_est, ci_ub), 23 | y = c(max_se, 0, max_se), 24 | linetype = ci_label, 25 | group = 2) 26 | ) 27 | # data$group <- NULL 28 | # data <- cbind(ci_lines, 29 | # data %>% 30 | # dplyr::select(-x, -y, -linetype) %>% 31 | # dplyr::slice(1:5)) 32 | ci_lines$y <- ci_lines$y * se_sign 33 | ci_lines 34 | }, 35 | required_aes = c("x", "y", "summary")) 36 | 37 | GeomFunnel <- ggplot2::ggproto("GeomFunnel", ggplot2::GeomLine, 38 | default_aes = ggplot2::aes(colour = "black", size = 0.75, 39 | linetype = 1, alpha = NA)) 40 | 41 | #' Funnel plot lines 42 | #' 43 | #' `geom_funnel()`` computes psuedo confidence limits for the summary estimate 44 | #' of a meta-analysis to be used in a funnel plot. 45 | #' 46 | #' @inheritParams ggplot2::geom_line 47 | #' @param ci_level the confidence level desired for the psuedo-CI lines. Between 48 | #' 0 and 1. Also used for line labels. 49 | #' @param log_summary a summary estimate (see [pull_summary()]) 50 | #' @param color,colour line color 51 | #' @param summary_label a string. The legend label for the summary line. 52 | #' @param ci_label a string. The legend label for the CI lines. Default is 53 | #' `NULL`, in which case the labels will be created based on `ci_level`. 54 | #' @export 55 | #' 56 | #' @examples 57 | #' 58 | #' library(ggplot2) 59 | #' 60 | #' ma <- meta_analysis(iud_cxca, yi = lnes, sei = selnes, slab = study_name) 61 | #' 62 | #' ggplot(ma, aes(x = estimate, y = std.error)) + 63 | #' geom_point() + 64 | #' geom_funnel(aes(summary = pull_summary(ma))) + 65 | #' scale_y_reverse() 66 | #' 67 | #' @importFrom purrr %||% 68 | geom_funnel <- function(mapping = NULL, data = NULL, ci_level = .95, log_summary = FALSE, 69 | colour = "black", color = NULL, position = "identity", 70 | na.rm = FALSE, summary_label = "Summary\nEstimate", 71 | ci_label = NULL, show.legend = NA, inherit.aes = TRUE, 72 | ...) { 73 | 74 | if (is.null(mapping)) { 75 | 76 | mapping <- ggplot2::aes(linetype = "funnel_lines", group = 1) 77 | 78 | } else { 79 | if (is.null(mapping$linetype)) mapping$linetype <- "funnel_lines" 80 | if (is.null(mapping$group)) mapping$group <- 1 81 | } 82 | ggplot2::layer( 83 | data = data, 84 | mapping = mapping, 85 | stat = StatFunnel, 86 | geom = GeomFunnel, 87 | position = position, 88 | show.legend = show.legend, 89 | inherit.aes = inherit.aes, 90 | params = list( 91 | na.rm = na.rm, 92 | ci_level = ci_level, 93 | log_summary = log_summary, 94 | summary_label = summary_label, 95 | ci_label = ci_label, 96 | colour = color %||% colour, 97 | ... 98 | ) 99 | ) 100 | } 101 | 102 | #' Log scales for continuous data (x & y) 103 | #' 104 | #' @param ... additional arguments passed to `scale_*_continuous()` 105 | #' @param breaks a vector of axis breaks 106 | #' 107 | #' @export 108 | #' 109 | #' @rdname log_scales 110 | scale_x_log <- function(..., breaks = scales::log_breaks()) { 111 | ggplot2::scale_x_continuous(..., trans = scales::log_trans(), 112 | breaks = breaks) 113 | } 114 | 115 | #' @export 116 | #' @rdname log_scales 117 | scale_y_log <- function(..., breaks = scales::log_breaks()) { 118 | ggplot2::scale_y_continuous(..., trans = scales::log_trans(), 119 | breaks = breaks) 120 | } 121 | -------------------------------------------------------------------------------- /R/glance.R: -------------------------------------------------------------------------------- 1 | #' Construct a one-row summary of meta-analysis model fit statistics. 2 | #' 3 | #' `glance()` computes a one-row summary of meta-analysis objects, 4 | #' including estimates of heterogenity and model fit. 5 | #' 6 | #' @param x a meta-analysis object. Currently supports `rma.uni` from the 7 | #' `metafor` package. 8 | #' @param ... additional arguments 9 | #' 10 | #' @return a `data.frame` 11 | #' @export 12 | #' 13 | #' @examples 14 | #' 15 | #' library(broom) 16 | #' library(metafor) 17 | #' rma(yi = lnes, sei = selnes, slab = study_name, data = iud_cxca) %>% 18 | #' glance() 19 | #' 20 | glance.rma.uni <- function(x, ...) { 21 | fit_stats <- metafor::fitstats(x) 22 | fit_stats <- fit_stats %>% 23 | t() %>% 24 | as.data.frame() 25 | names(fit_stats) <- stringr::str_replace(names(fit_stats), "\\:", "") 26 | data.frame(i.squared = x$I2, h.squared = x$H2, tau.squared = x$tau2, fit_stats) 27 | } 28 | -------------------------------------------------------------------------------- /R/influence.R: -------------------------------------------------------------------------------- 1 | #' Sensitivity analyses of meta-analysis results 2 | #' 3 | #' Conduct leave-one-out or group-wise sensitivity analyses of meta-analysis 4 | #' results. 5 | #' 6 | #' @param x a `tbl` produced by [meta_analysis()] or by [broom::tidy()] 7 | #' @param type type of sensitvity analysis. 8 | #' @param prefix the prefix for the model result variables, e.g. estimate. 9 | #' @param conf.int logical. Should confidence intervals be included? Default is 10 | #' `TRUE`. 11 | #' @param exponentiate logical. Should results be exponentiated? Default is 12 | #' `FALSE`. 13 | #' @param glance logical. Should sensitivity model fit statistics be included? 14 | #' Default is `FALSE`. 15 | #' @param .f a function for sensitivity analysis. Default is 16 | #' [metafor::leave1out] 17 | #' @param ... additional arguments 18 | #' 19 | #' @return a `tbl` 20 | #' @export 21 | #' 22 | #' @examples 23 | #' 24 | #' meta_analysis(iud_cxca, yi = lnes, sei = selnes, slab = study_name) %>% 25 | #' sensitivity() 26 | #' 27 | sensitivity <- function(x, type = "leave1out", prefix = "l1o_", 28 | conf.int = TRUE, exponentiate = FALSE, glance = FALSE, 29 | .f = metafor::leave1out, ...) { 30 | if (type == "leave1out") { 31 | .ma <- pull_meta(x) 32 | l1out <- .f(.ma) %>% 33 | as.data.frame() %>% 34 | tibble::rownames_to_column("study") 35 | 36 | var_names <- c("study", "estimate", "std.error", "statistic", "p.value", "conf.low", 37 | "conf.high") 38 | 39 | if (glance) { 40 | var_names <- c(var_names, "q", "qp", "tau.squared", "i.squared", "h.squared") 41 | names(l1out) <- paste0(prefix, var_names) 42 | } else { 43 | l1out <- dplyr::select(l1out, -Q:-H2) 44 | names(l1out) <- paste0(prefix, var_names) 45 | } 46 | 47 | if (exponentiate) { 48 | l1out[, paste0(prefix, "estimate")] <- exp(l1out[, paste0(prefix, "estimate")]) 49 | l1out[, paste0(prefix, "conf.low")] <- exp(l1out[, paste0(prefix, "conf.low")]) 50 | l1out[, paste0(prefix, "conf.high")] <- exp(l1out[, paste0(prefix, "conf.high")]) 51 | } 52 | 53 | if (!conf.int) { 54 | l1out <- l1out[-which(names(l1out) %in% paste0(prefix, c("conf.low", "conf.high")))] 55 | } 56 | 57 | ma_data <- broom::tidy(.ma, conf.int = conf.int, exponentiate = exponentiate, 58 | include_studies = FALSE) %>% 59 | dplyr::select(-type) 60 | 61 | names(ma_data) <- paste0(prefix, names(ma_data)) 62 | 63 | dplyr::bind_rows(l1out, ma_data) %>% 64 | dplyr::left_join(x, ., by = c("study" = paste0(prefix, "study"))) 65 | 66 | } else if (type == "group_by") { 67 | 68 | } 69 | } 70 | 71 | #' Cumulative sensitivity analyses of meta-analysis results 72 | #' 73 | #' Conduct cumulative sensitivity analyses of meta-analysis results by adding 74 | #' studies in one at a time. `cumulative` works well with [dplyr::arrange()]. 75 | #' 76 | #' @param x a `tbl` produced by [meta_analysis()] or by [broom::tidy()] 77 | #' @param prefix the prefix for the model result variables, e.g. estimate. 78 | #' @param conf.int logical. Should confidence intervals be included? Default is 79 | #' `TRUE`. 80 | #' @param exponentiate logical. Should results be exponentiated? Default is 81 | #' `FALSE`. 82 | #' @param glance logical. Should sensitivity model fit statistics be included? 83 | #' Default is `FALSE`. 84 | #' @param .f a function for sensitivity analysis. Default is [metafor::cumul] 85 | #' @param ... additional arguments 86 | #' 87 | #' @return a `tbl` 88 | #' @export 89 | #' 90 | #' @examples 91 | #' 92 | #' library(dplyr) 93 | #' 94 | #' meta_analysis(iud_cxca, yi = lnes, sei = selnes, slab = study_name) %>% 95 | #' arrange(desc(weight)) %>% 96 | #' cumulative() 97 | #' 98 | cumulative <- function(x, prefix = "cumul_", 99 | conf.int = TRUE, exponentiate = FALSE, glance = FALSE, 100 | .f = metafor::cumul, ...) { 101 | .ma <- pull_meta(x) 102 | key_df <- data.frame(study = as.character(.ma$slab), 103 | .study_order_id = seq_along(.ma$slab), 104 | stringsAsFactors = FALSE) 105 | .study_order_id <- dplyr::left_join(x, key_df, by = "study") %>% 106 | dplyr::filter(type == "study") %>% 107 | dplyr::pull(.study_order_id) 108 | 109 | cumul_df <- .f(.ma, order = .study_order_id) %>% 110 | as.data.frame() %>% 111 | tibble::rownames_to_column("study") 112 | 113 | var_names <- c("study", "estimate", "std.error", "statistic", "p.value", "conf.low", 114 | "conf.high") 115 | 116 | if (glance) { 117 | var_names <- c(var_names, "q", "qp", "tau.squared", "i.squared", "h.squared") 118 | names(cumul_df) <- paste0(prefix, var_names) 119 | } else { 120 | cumul_df <- dplyr::select(cumul_df, -QE:-H2) 121 | names(cumul_df) <- paste0(prefix, var_names) 122 | } 123 | 124 | if (exponentiate) { 125 | cumul_df[, paste0(prefix, "estimate")] <- exp(cumul_df[, paste0(prefix, "estimate")]) 126 | cumul_df[, paste0(prefix, "conf.low")] <- exp(cumul_df[, paste0(prefix, "conf.low")]) 127 | cumul_df[, paste0(prefix, "conf.high")] <- exp(cumul_df[, paste0(prefix, "conf.high")]) 128 | } 129 | 130 | if (!conf.int) { 131 | cumul_df <- cumul_df[-which(names(cumul_df) %in% paste0(prefix, c("conf.low", "conf.high")))] 132 | } 133 | 134 | ma_data <- broom::tidy(.ma, conf.int = conf.int, exponentiate = exponentiate, 135 | include_studies = FALSE) %>% 136 | dplyr::select(-type) 137 | 138 | names(ma_data) <- paste0(prefix, names(ma_data)) 139 | 140 | dplyr::bind_rows(cumul_df, ma_data) %>% 141 | dplyr::left_join(x, ., by = c("study" = paste0(prefix, "study"))) %>% 142 | dplyr::arrange(type) 143 | } 144 | -------------------------------------------------------------------------------- /R/meta_analysis.R: -------------------------------------------------------------------------------- 1 | #' Add a meta-analysis to a tbl 2 | #' 3 | #' `add_meta()` add a meta-analysis object to a tidied meta-analysis. 4 | #' 5 | #' @param x a `data.frame` produced by `tidy()` 6 | #' @param meta a meta-analysis object (e.g. `rma.uni`) 7 | #' @param ... additional arguments to `as.tbl` 8 | #' 9 | #' @return a `tbl` with a `listcol`, `meta`, containing the meta-analysis 10 | #' @export 11 | #' 12 | #' @examples 13 | #' 14 | #' library(metafor) 15 | #' library(broom) 16 | #' 17 | #' ma <- rma(yi = lnes, sei = selnes, slab = study_name, data = iud_cxca) 18 | #' 19 | #' ma %>% 20 | #' tidy() %>% 21 | #' add_meta(ma) 22 | #' 23 | add_meta <- function(x, meta, ...) { 24 | dplyr::as.tbl(x, ...) %>% 25 | dplyr::mutate(meta = list(meta), 26 | meta = ifelse(study == "Overall" & type == "summary", meta, list(NULL))) 27 | } 28 | 29 | 30 | #' Meta-Analysis 31 | #' 32 | #' A wrapper for meta-analytic functions that automatically tidies it and adds 33 | #' the meta-analysis object to the `tbl` in a `listcol`. 34 | #' 35 | #' @param .data a `data.frame` containing the data for the meta-analysis 36 | #' @param .f a meta-analysis function. Default is [metafor::rma] 37 | #' @param ... additional arguments passed to `.f` 38 | #' @param conf.int logical. Include confidence intervals? 39 | #' @param exponentiate logical. Should the estimates and (if `conf.int` = 40 | #' `TRUE`) confidence intervals be exponentiated? 41 | #' @param include_studies logical. Include indidiual study coefficients? 42 | #' @param bind_data logical. Bind original data to output? 43 | #' @param weights logical. Include study weights in output? 44 | #' 45 | #' @return a `tbl` 46 | #' 47 | #' @export 48 | #' 49 | #' @examples 50 | #' 51 | #' meta_analysis(iud_cxca, yi = lnes, sei = selnes, slab = study_name) 52 | #' 53 | #' @importFrom rlang !!! 54 | meta_analysis <- function(.data, .f = metafor::rma, ..., conf.int = TRUE, 55 | exponentiate = FALSE, include_studies = TRUE, 56 | bind_data = FALSE, weights = TRUE) { 57 | 58 | .args <- rlang::enexprs(...) 59 | 60 | if (dplyr::is_grouped_df(.data)) { 61 | group_var <- dplyr::group_vars(.data) 62 | group_is_factor <- is.factor(.data[[group_var]]) 63 | .subgroup <- .data %>% 64 | tidyr::nest() %>% 65 | dplyr::mutate(meta = purrr::map(data, 66 | ~rlang::eval_tidy(rlang::expr(meta_analysis(.x, .f = .f, !!!.args, 67 | conf.int = conf.int, exponentiate = exponentiate, 68 | bind_data = bind_data, weights = FALSE))) 69 | )) %>% 70 | dplyr::select(-data) %>% 71 | tidyr::unnest() %>% 72 | dplyr::ungroup() %>% 73 | dplyr::mutate(study = ifelse(study == "Overall", 74 | paste("Subgroup:", !!!rlang::sym(group_var)), 75 | study)) 76 | 77 | .meta_data <- .data %>% 78 | dplyr::ungroup() %>% 79 | meta_analysis(.f = .f, ..., conf.int = conf.int, 80 | exponentiate = exponentiate, bind_data = bind_data, 81 | include_studies = FALSE, weights = FALSE) %>% 82 | dplyr::mutate(!!group_var := "Summary") 83 | if (group_is_factor) { 84 | fct_subgroup <- .subgroup[[group_var]] 85 | fct_overall <- .meta_data[[group_var]] 86 | unified <- forcats::fct_unify(list(fct_subgroup, as.factor(fct_overall))) 87 | .subgroup[[group_var]] <- unified[[1]] 88 | .meta_data[[group_var]] <- unified[[2]] 89 | } 90 | 91 | .meta_data <- dplyr::bind_rows(.subgroup, .meta_data) 92 | 93 | if (weights) .meta_data <- add_weights(.meta_data, group = !!rlang::sym(group_var)) 94 | 95 | return(.meta_data) 96 | } 97 | 98 | .meta <- rlang::eval_tidy(rlang::expr(.f(data = .data, !!! .args))) 99 | .meta_data <- .meta %>% 100 | broom::tidy(conf.int = conf.int, exponentiate = exponentiate, 101 | include_studies = include_studies) %>% 102 | add_meta(.meta) 103 | if (weights) .meta_data <- add_weights(.meta_data) 104 | if (bind_data) { 105 | dplyr::bind_cols(.meta_data, dplyr::add_row(.data)) 106 | } else { 107 | .meta_data 108 | } 109 | } 110 | 111 | #' Pull the meta-analysis object 112 | #' 113 | #' @param x a tidied meta-analysis 114 | #' 115 | #' @return an object created by a meta-analysis 116 | #' @export 117 | #' 118 | #' @examples 119 | #' 120 | #' meta_analysis(iud_cxca, yi = lnes, sei = selnes, slab = study_name) %>% 121 | #' pull_meta() 122 | pull_meta <- function(x) { 123 | x %>% 124 | dplyr::filter(study == "Overall", type == "summary") %>% 125 | dplyr::pull(meta) %>% 126 | purrr::pluck(1) 127 | } 128 | 129 | #' Pull the meta-analysis summary estimate 130 | #' 131 | #' @param x a tidied meta-analysis 132 | #' @param conf.int logical. Include confidence intervals? 133 | #' 134 | #' @return an object created by a meta-analysis 135 | #' @export 136 | #' 137 | #' @examples 138 | #' 139 | #' meta_analysis(iud_cxca, yi = lnes, sei = selnes, slab = study_name) %>% 140 | #' pull_summary() 141 | #' 142 | pull_summary <- function(x, conf.int = FALSE) { 143 | est <- x %>% 144 | dplyr::filter(study == "Overall", type == "summary") %>% 145 | dplyr::pull(estimate) %>% 146 | purrr::pluck(1) 147 | 148 | if (conf.int) { 149 | cil <- x %>% 150 | dplyr::filter(study == "Overall", type == "summary") %>% 151 | dplyr::pull(conf.low) %>% 152 | purrr::pluck(1) 153 | ciu <- x %>% 154 | dplyr::filter(study == "Overall", type == "summary") %>% 155 | dplyr::pull(conf.high) %>% 156 | purrr::pluck(1) 157 | est <- c(est, cil, ciu) 158 | } 159 | 160 | est 161 | } 162 | -------------------------------------------------------------------------------- /R/quick_plots.R: -------------------------------------------------------------------------------- 1 | #' Quickly plot common visualizations for meta-analyses 2 | #' 3 | #' `forest_plot()` presents study and summary estimates. `influence_plot()` 4 | #' shows the forest plot of senstivity analyses using `senstivity()`. 5 | #' `cumulative_plot()` shows the forest plot for `cumulative()`. `funnel_plot()` 6 | #' plots standard errors against the summary esitimate to assess publication 7 | #' bias. 8 | #' 9 | #' @param x a tidied meta-analysis 10 | #' @param ... additional arguments 11 | #' @param estimate variable name of point estimates 12 | #' @param study variable name of study labels 13 | #' @param size point size; either an aesthetic variable or a specific shape. 14 | #' @param shape shape of the points; either an aesthetic variable or a specific 15 | #' shape. 16 | #' @param col color of the points and lines; either an aesthetic variable or a 17 | #' specific color. 18 | #' @param xmin lower confidence interval variable name 19 | #' @param xmax upper confidence interval variable name 20 | #' @param group a grouping variable 21 | #' @param alpha transparancy level 22 | #' @param height line height for error bars 23 | #' @param std.error variable name of standard error variable 24 | #' @param reverse_y logical. Should the y-axis be reversed? 25 | #' @param log_summary logical. Should the estimate and confidence intervals be 26 | #' log-transformed? 27 | #' @param sum_lines logical. Should vertical lines demarcating the summary 28 | #' estimate and confidence intervals be included? 29 | #' 30 | #' @return a `ggplot2` object 31 | #' @export 32 | #' 33 | #' @examples 34 | #' 35 | #' library(dplyr) 36 | #' 37 | #' ma <- iud_cxca %>% 38 | #' group_by(group) %>% 39 | #' meta_analysis(yi = lnes, sei = selnes, slab = study_name) 40 | #' 41 | #' forest_plot(ma) 42 | #' 43 | #' funnel_plot(ma) 44 | #' 45 | #' ma %>% 46 | #' sensitivity() %>% 47 | #' influence_plot() 48 | #' 49 | #' ma %>% 50 | #' cumulative() %>% 51 | #' cumulative_plot() 52 | #' 53 | #' @rdname quickplots 54 | #' 55 | #' @importFrom rlang !! 56 | forest_plot <- function(x, estimate = estimate, study = study, size = weight, 57 | shape = type, col = type, xmin = conf.low, 58 | xmax = conf.high, group = NULL, alpha = .75, height = 0, 59 | ...) { 60 | 61 | .estimate <- rlang::enquo(estimate) 62 | .study <- rlang::enquo(study) 63 | .studycol <- rlang::quo_text(.study) 64 | .size <- rlang::enquo(size) 65 | .shape <- rlang::enquo(shape) 66 | .col <- rlang::enquo(col) 67 | .group <- rlang::enquo(group) 68 | .groupcol <- rlang::quo_text(.group) 69 | .xmin <- rlang::enquo(xmin) 70 | .xmax <- rlang::enquo(xmax) 71 | 72 | if (is.null(x$weight)) { 73 | 74 | } 75 | 76 | x <- x %>% 77 | dplyr::mutate(!!.studycol := lock_order(!!.study)) 78 | 79 | if (!rlang::quo_is_null(.group)) { 80 | x <- x %>% 81 | dplyr::mutate(!!.groupcol := lock_order(!!.group, rev = FALSE)) 82 | } 83 | 84 | p <- x %>% 85 | ggplot2::ggplot(ggplot2::aes(x = !!.estimate, y = !!.study, 86 | shape = !!.shape, col = !!.col)) + 87 | ggplot2::geom_point(ggplot2::aes(size = !!.size), alpha = alpha) + 88 | theme_forest() 89 | 90 | if (!rlang::quo_is_null(.xmin)) { 91 | p <- p + ggplot2::geom_errorbarh(ggplot2::aes(xmin = !!.xmin, 92 | xmax = !!.xmax), 93 | height = height, 94 | alpha = alpha) 95 | } 96 | 97 | if (!rlang::quo_is_null(.group)) { 98 | p <- p + ggplot2::facet_grid(ggplot2::vars(!!.group), scales = "free", 99 | space = "free", switch = "y") 100 | } 101 | p 102 | } 103 | 104 | #' @rdname quickplots 105 | #' @export 106 | #' @importFrom rlang !! 107 | influence_plot <- function(x, estimate = l1o_estimate, study = study, size = 4, 108 | shape = 15, col = type, xmin = l1o_conf.low, 109 | xmax = l1o_conf.high, group = NULL, alpha = .75, height = 0, 110 | sum_lines = TRUE, ...) { 111 | 112 | .estimate <- rlang::enquo(estimate) 113 | .study <- rlang::enquo(study) 114 | .col <- rlang::enquo(col) 115 | .studycol <- rlang::quo_text(.study) 116 | .group <- rlang::enquo(group) 117 | .groupcol <- rlang::quo_text(.group) 118 | .xmin <- rlang::enquo(xmin) 119 | .xmax <- rlang::enquo(xmax) 120 | 121 | 122 | vline_data <- data.frame(cuts = pull_summary(x, conf.int = TRUE), 123 | type = c("Estimate", "95% CI", "95% CI")) 124 | x <- x %>% 125 | dplyr::filter(!stringr::str_detect(study, "Subgroup")) %>% 126 | dplyr::mutate(!!.studycol := lock_order(!!.study)) 127 | 128 | if (!rlang::quo_is_null(.group)) { 129 | x <- x %>% 130 | dplyr::mutate(!!.groupcol := lock_order(!!.group, rev = FALSE)) 131 | } 132 | 133 | 134 | 135 | p <- x %>% 136 | dplyr::mutate(estimate = !!.estimate, !!.studycol := lock_order(!!.study)) %>% 137 | ggplot2::ggplot(ggplot2::aes(x = estimate, y = !!.study, col = forcats::fct_rev(!!.col))) + 138 | ggplot2::geom_point(shape = shape, size = size, alpha = alpha) + 139 | theme_forest() 140 | 141 | if (sum_lines) p <- p + ggplot2::geom_vline(data = vline_data, 142 | ggplot2::aes(xintercept = cuts, 143 | linetype = type)) 144 | 145 | if (!rlang::quo_is_null(.xmin)) { 146 | p <- p + ggplot2::geom_errorbarh(ggplot2::aes(xmin = !!.xmin, 147 | xmax = !!.xmax), 148 | height = height, 149 | alpha = alpha) 150 | } 151 | 152 | if (!rlang::quo_is_null(.group)) { 153 | p <- p + ggplot2::facet_grid(ggplot2::vars(!!.group), scales = "free", 154 | space = "free", switch = "y") 155 | } 156 | p 157 | } 158 | 159 | 160 | #' @rdname quickplots 161 | #' @export 162 | #' @importFrom rlang !! 163 | cumulative_plot <- function(x, estimate = cumul_estimate, study = study, size = 4, 164 | shape = 15, col = type, xmin = cumul_conf.low, 165 | xmax = cumul_conf.high, group = NULL, alpha = .75, height = 0, 166 | sum_lines = TRUE, ...) { 167 | .estimate <- rlang::enquo(estimate) 168 | .study <- rlang::enquo(study) 169 | .col <- rlang::enquo(col) 170 | .group <- rlang::enquo(group) 171 | .xmin <- rlang::enquo(xmin) 172 | .xmax <- rlang::enquo(xmax) 173 | 174 | influence_plot(x = x, estimate = !!.estimate, study = !!.study, size = size, 175 | shape = shape, col = !!.col, xmin = !!.xmin, 176 | xmax = !!.xmax, group = !!.group, alpha = alpha, height = height, 177 | sum_lines = sum_lines, ...) 178 | } 179 | 180 | 181 | #' @rdname quickplots 182 | #' @export 183 | #' @importFrom rlang !! 184 | funnel_plot <- function(x, estimate = estimate, std.error = std.error, size = 3, 185 | shape = NULL, col = NULL, alpha = .75, reverse_y = TRUE, 186 | log_summary = FALSE, ...) { 187 | 188 | .estimate <- rlang::enquo(estimate) 189 | .std.error <- rlang::enquo(std.error) 190 | .shape <- rlang::enquo(shape) 191 | .col <- rlang::enquo(col) 192 | 193 | mapping <- ggplot2::aes(x = !!.estimate, y = !!.std.error, 194 | col = !!.col, shape = !!.shape) 195 | 196 | if (rlang::quo_is_null(.col)) mapping$colour <- NULL 197 | if (rlang::quo_is_null(.shape)) mapping$shape <- NULL 198 | 199 | 200 | p <- x %>% 201 | dplyr::filter(type == "study") %>% 202 | ggplot2::ggplot(mapping) + 203 | ggplot2::geom_point(size = size) + 204 | geom_funnel(ggplot2::aes(summary = pull_summary(x)), 205 | log_summary = log_summary) + 206 | theme_meta() + 207 | ggplot2::theme(legend.position = "right") + 208 | ggplot2::scale_linetype_discrete(name = "") 209 | 210 | if (log_summary) p <- p + scale_x_log() 211 | if (reverse_y) p <- p + ggplot2::scale_y_reverse() 212 | 213 | p 214 | } 215 | 216 | #' Lock the order of the data in the plot 217 | #' 218 | #' `lock_order()` locks the order of the of an axis variable exactly as it 219 | #' appears in the data, rather than from the bottom up (for factors and 220 | #' numerics) or in alphabetical order (for characters). 221 | #' 222 | #' @param var a variable to lock 223 | #' @param rev logical. Should the order be reversed to make it appear on the 224 | #' plot as in the data? Default is `TRUE`. 225 | #' 226 | #' @return a factor 227 | #' @export 228 | #' 229 | #' @examples 230 | #' 231 | #' library(ggplot2) 232 | #' 233 | #' meta_analysis(iud_cxca, yi = lnes, sei = selnes, slab = study_name) %>% 234 | #' ggplot(aes(x = estimate, y = lock_order(study))) + 235 | #' geom_point() 236 | lock_order <- function(var, rev = TRUE) { 237 | var <- forcats::fct_inorder(var) 238 | if (rev) var <- forcats::fct_rev(var) 239 | var 240 | } 241 | 242 | #' Group summary estimates together 243 | #' 244 | #' The default in `tidymeta` is to put subgroup estimates in the same group as 245 | #' the estimates; `sub2summary()` gives them a value of "Overall", which groups 246 | #' all summaries together. 247 | #' 248 | #' @param x a tidied meta-analysis 249 | #' @param group a grouping variable 250 | #' @param ... additional arguments 251 | #' 252 | #' @return a `tbl` 253 | #' @export 254 | #' 255 | #' @examples 256 | #' 257 | #' library(dplyr) 258 | #' 259 | #' iud_cxca %>% 260 | #' group_by(group) %>% 261 | #' meta_analysis(yi = lnes, sei = selnes, slab = study_name) %>% 262 | #' sub2summary(group) 263 | #' 264 | #' @importFrom rlang !! 265 | sub2summary <- function(x, group, ...) { 266 | .group <- rlang::enquo(group) 267 | .groupcol <- rlang::quo_text(.group) 268 | x %>% 269 | dplyr::mutate(!!.groupcol := ifelse(stringr::str_detect(study, "Subgroup"), 270 | "Summary", 271 | !!.group)) %>% 272 | dplyr::arrange(type) 273 | } 274 | 275 | -------------------------------------------------------------------------------- /R/text_table.R: -------------------------------------------------------------------------------- 1 | #' Quickly produce text tables to accompany forest plots. 2 | #' 3 | #' @param .data a `data.frame` 4 | #' @param ... bare variable names to include in the table 5 | #' @param study name of study variable 6 | #' @param group a grouping variable 7 | #' @param show_y_facets logical. Should y-axis facets be included if grouped? 8 | #' @param show_y_axis logical. Should study names be included on y-axis? 9 | #' @param show_grid logical. Show grid lines? 10 | #' @param size text size 11 | #' 12 | #' @return a `ggplot2` object 13 | #' @export 14 | #' 15 | #' @examples 16 | #' 17 | #' meta_analysis(iud_cxca, yi = lnes, sei = selnes, slab = study_name) %>% 18 | #' text_table(weight) 19 | #' 20 | #' @importFrom rlang !! !!! 21 | text_table <- function(.data, ..., study = study, group = NULL, 22 | show_y_facets = TRUE, show_y_axis = TRUE, 23 | show_grid = FALSE, size = 3.75) { 24 | 25 | .study_id <- rlang::enquo(study) 26 | .study_col <- rlang::quo_text(.study_id) 27 | .vars <- rlang::enquos(...) 28 | .group <- rlang::enquo(group) 29 | if (rlang::quo_is_null(.group)) { 30 | 31 | p <- dplyr::select(.data, !!.study_id, !!!.vars) %>% 32 | tidyr::gather(key, value, -!!.study_id) %>% 33 | dplyr::mutate(key = forcats::fct_inorder(key), 34 | !!.study_col := lock_order(!!.study_id)) %>% 35 | ggplot2::ggplot(ggplot2::aes(x = 1, y = !!.study_id)) + 36 | ggplot2::geom_text(ggplot2::aes(label = value), size = size) + 37 | ggplot2::facet_grid(cols = ggplot2::vars(key), scales = "free", space = "free") + 38 | theme_forest() + 39 | ggplot2::theme(axis.ticks.x = ggplot2::element_blank(), 40 | axis.title = ggplot2::element_blank(), 41 | axis.text.x = ggplot2::element_blank()) 42 | } else { 43 | .group_col <- rlang::quo_text(.group) 44 | p <- dplyr::select(.data, !!.study_id, !!.group, !!!.vars) %>% 45 | tidyr::gather(key, value, -!!.study_id, -!!.group) %>% 46 | dplyr::mutate(key = forcats::fct_inorder(key), 47 | !!.study_col := lock_order(!!.study_id), 48 | !!.group_col := forcats::fct_inorder(!!.group)) %>% 49 | ggplot2::ggplot(ggplot2::aes(x = 1, y = !!.study_id)) + 50 | ggplot2::geom_text(ggplot2::aes(label = value), size = size) + 51 | ggplot2::facet_grid(rows = ggplot2::vars(!!.group), 52 | cols = ggplot2::vars(key), 53 | scales = "free", space = "free", switch = "y") + 54 | theme_forest() + 55 | ggplot2::theme(axis.ticks.x = ggplot2::element_blank(), 56 | axis.title = ggplot2::element_blank(), 57 | axis.text.x = ggplot2::element_blank()) 58 | } 59 | 60 | if (!show_y_facets) p <- p + ggplot2::theme(strip.background.y = ggplot2::element_blank(), 61 | strip.text.y = ggplot2::element_blank()) 62 | if (!show_grid) p <- p + ggplot2::theme(panel.grid = ggplot2::element_blank()) 63 | if (!show_y_axis) p <- p + ggplot2::theme(axis.text.y = ggplot2::element_blank()) 64 | 65 | p 66 | } 67 | -------------------------------------------------------------------------------- /R/themes.R: -------------------------------------------------------------------------------- 1 | #' Minimalist theme with meta-analyses in mind 2 | #' 3 | #' `theme_meta()` is a base theme, while `theme_forest()` has forest plots in 4 | #' mind, meaning it removes most legends and sets squares and diamonds as the 5 | #' default point shapes. 6 | #' 7 | #' @param font_size font size 8 | #' @param font_family font family 9 | #' @param line_size line size 10 | #' 11 | #' @export 12 | #' 13 | #' @rdname metathemes 14 | #' @importFrom ggplot2 %+replace% 15 | theme_meta <- function(font_size = 14, font_family = "", line_size = .5) { 16 | ggplot2::theme_minimal() %+replace% 17 | ggplot2::theme( 18 | text = ggplot2::element_text(family = font_family, face = "plain", colour = "black", 19 | size = font_size, hjust = 0.5, vjust = 0.5, angle = 0, lineheight = .9, 20 | margin = ggplot2::margin(), debug = FALSE), 21 | strip.text.y = ggplot2::element_text(angle = 180), 22 | strip.background = ggplot2::element_rect(color = "grey86", fill = "grey92"), 23 | axis.text.y = ggplot2::element_text(size = 12, hjust = 1), 24 | axis.text.x = ggplot2::element_text(size = 12), 25 | complete = TRUE 26 | ) 27 | } 28 | 29 | #' @export 30 | #' @rdname metathemes 31 | theme_forest <- function(font_size = 14, font_family = "", line_size = .5) { 32 | list( 33 | theme_meta(font_size = font_size, font_family = font_family, line_size = line_size), 34 | ggplot2::theme(axis.title.y = ggplot2::element_blank(), 35 | legend.position = "none"), 36 | ggplot2::scale_shape_manual(values = c(15, 18)), 37 | ggplot2::scale_size_continuous(range = c(3, 10)) 38 | ) 39 | } 40 | -------------------------------------------------------------------------------- /R/tidy.R: -------------------------------------------------------------------------------- 1 | #' Tidying methods for meta-analyis objects 2 | #' 3 | #' These methods tidy the results of meta-analysis objects 4 | #' 5 | #' @param x a meta-analysis object. Currently supports `rma.uni` from the 6 | #' `metafor` package. 7 | #' @param conf.int logical. Include confidence intervals? 8 | #' @param exponentiate logical. Should the estimates and (if `conf.int` = 9 | #' `TRUE`) confidence intervals be exponentiated? 10 | #' @param include_studies logical. Should individual studies be included in the 11 | #' output? 12 | #' @param ... additional arguments 13 | #' @param measure measure type. See [metafor::rma()] 14 | #' 15 | #' @return a `data.frame` 16 | #' @export 17 | #' 18 | #' @examples 19 | #' library(broom) 20 | #' library(metafor) 21 | #' rma(yi = lnes, sei = selnes, slab = study_name, data = iud_cxca) %>% 22 | #' tidy() 23 | #' 24 | #' @rdname tidiers 25 | tidy.rma.uni <- function(x, conf.int = TRUE, exponentiate = FALSE, 26 | include_studies = TRUE, measure = "GEN", ...) { 27 | if (!inherits(x, "rma.uni")) stop("`x` must be of class `rma.uni`") 28 | 29 | estimates <- metafor::escalc(yi = x$yi.f, vi = x$vi.f, measure = measure) %>% 30 | metafor2df() 31 | 32 | estimates <- cbind(x$slab, "study", estimates[, c("yi", "sei", "zi")], NA, 33 | estimates[, c("ci.lb", "ci.ub")], stringsAsFactors = FALSE) 34 | names(estimates) <- c("study", "type", "estimate", "std.error", "statistic", 35 | "p.value", "conf.low", "conf.high") 36 | 37 | results <- data.frame(study = "Overall", type = "summary", 38 | estimate = x$beta[1], std.error = x$se, 39 | statistic = x$zval, p.value = x$pval, 40 | conf.low = x$ci.lb, conf.high = x$ci.ub, 41 | stringsAsFactors = FALSE) 42 | .data <- if (include_studies) rbind(estimates, results) else results 43 | 44 | if (exponentiate) { 45 | .data$estimate <- exp(.data$estimate) 46 | .data$conf.low <- exp(.data$conf.low) 47 | .data$conf.high <- exp(.data$conf.high) 48 | } 49 | 50 | if (!conf.int) { 51 | .data <- .data[-which(names(.data) %in% c("conf.low", "conf.high"))] 52 | } 53 | 54 | attributes(.data$study) <- NULL 55 | 56 | .data 57 | } 58 | -------------------------------------------------------------------------------- /R/utils-pipe.R: -------------------------------------------------------------------------------- 1 | #' Pipe operator 2 | #' 3 | #' See \code{magrittr::\link[magrittr]{\%>\%}} for details. 4 | #' 5 | #' @name %>% 6 | #' @rdname pipe 7 | #' @keywords internal 8 | #' @export 9 | #' @importFrom magrittr %>% 10 | #' @usage lhs \%>\% rhs 11 | NULL 12 | -------------------------------------------------------------------------------- /R/utils.R: -------------------------------------------------------------------------------- 1 | # variables used in various NSE calls 2 | utils::globalVariables( 3 | c(".", 4 | "study", 5 | "pred", 6 | "se", 7 | "pi.lb", 8 | "pi.ub", 9 | ".fitted", 10 | ".pil.fit", 11 | ".piu.fit", 12 | "meta", 13 | "study", 14 | "type", 15 | "residuals", 16 | "rstandard", 17 | "resid", 18 | "weights", 19 | "weight", 20 | "type", 21 | "hat", 22 | "cook.d", 23 | "rstudent", 24 | "dffits", 25 | "cov.r", 26 | "tau2.del", 27 | "dfbetas", 28 | "QE", 29 | "H2", 30 | "cumul_estimate", 31 | "cumul_conf.low", 32 | "cumul_conf.high", 33 | "conf.low", 34 | "conf.high", 35 | ":=", 36 | "l1o_estimate", 37 | "l1o_conf.low", 38 | "l1o_conf.high", 39 | "cuts", 40 | "data", 41 | "key", 42 | "value", 43 | "QE.del", 44 | "estimate", 45 | "Q" 46 | ) 47 | ) 48 | 49 | metafor2df <- function(x) { 50 | x %>% 51 | summary() %>% 52 | as.data.frame(stringsAsFactors = FALSE) 53 | } 54 | -------------------------------------------------------------------------------- /README.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | output: github_document 3 | --- 4 | 5 | 6 | 7 | ```{r setup, include = FALSE} 8 | knitr::opts_chunk$set( 9 | collapse = TRUE, 10 | comment = "#>", 11 | fig.path = "man/figures/README-", 12 | out.width = "100%", 13 | fig.height = 8, 14 | dpi = 320 15 | ) 16 | #[![AppVeyor build status](https://ci.appveyor.com/api/projects/status/github/malcolmbarrett/tidymeta?branch=master&svg=true)](https://ci.appveyor.com/project/malcolmbarrett/tidymeta) 17 | ``` 18 | 19 | [![Travis build status](https://travis-ci.org/malcolmbarrett/tidymeta.svg?branch=master)](https://travis-ci.org/malcolmbarrett/tidymeta) 20 | 21 | # tidymeta 22 | 23 | Tidy and plot meta-analyses from popular meta-analytic tools in R. Currently in early development. 24 | 25 | ## Installation 26 | 27 | `tidymeta` requires the development version of several packages, including `ggplot2`, to function correctly. You can install the required packages for this vignette with the following code: 28 | 29 | ```{r, eval=FALSE} 30 | install.packages(c("devtools", "yaml", "ggrepel")) 31 | library(devtools) 32 | install_github("r-lib/rlang") 33 | install_github("malcolmbarrett/tidymeta") 34 | install_github("malcolmbarrett/mbmisc") 35 | install_github("tidyverse/ggplot2") 36 | ``` 37 | 38 | # Tidy Meta-Analysis 39 | 40 | `tidymeta` is a toolkit for working with meta-analyses in R. Currently, it includes a data set, called `iud_cxca`, for a meta-analysis of the relationship between IUD use and cervical cancer. 41 | 42 | ```{r, warning = FALSE, message = FALSE} 43 | library(tidymeta) 44 | library(ggplot2) 45 | library(dplyr) 46 | library(broom) 47 | 48 | iud_cxca 49 | ``` 50 | 51 | `tidymeta` includes `broom` methods for cleaning meta-analysis results, although it currently only supports the `metafor` package. The `tidy()` function in `broom` puts results into a tidy data frame. 52 | 53 | ```{r, message = FALSE} 54 | library(metafor) 55 | meta4 <- rma(yi = lnes, sei = selnes, data = iud_cxca) 56 | tidy(meta4) %>% 57 | as_tibble() # for space 58 | ``` 59 | 60 | `tidymeta` also includes wrapper functions for working with meta-analysis packages in the context of the tidyverse. The main function for this is `meta_analysis()`, which models and tidies the object, as well as storing the results in the `meta` column to facilitate other analysis. 61 | 62 | ```{r} 63 | # same as above but stores the meta-analysis object 64 | iud_cxca %>% 65 | meta_analysis(yi = lnes, sei = selnes, slab = study_name) 66 | ``` 67 | 68 | `tidymeta` doesn't actually do meta-analysis; it unifies existing tools with the tidyverse. The benefit of this approach is that you can do meta-analyses with tidy tools in mind. For example, if you want to conduct a sub-group analysis, you can use the `group_by()` function from `dplyr`. Here, `group` is a variable with information about study design. 69 | 70 | ```{r} 71 | ma <- iud_cxca %>% 72 | group_by(group) %>% 73 | meta_analysis(yi = lnes, sei = selnes, slab = study_name, exponentiate = TRUE) 74 | 75 | ma 76 | ``` 77 | 78 | You can also do sensitivy analyses and cumulative analyses with `sensitivity()` and `cumulative()`. 79 | 80 | # Visualization for Meta-Analysis 81 | 82 | `tidymeta` includes functionality for working with results in `ggplot2`, including meta-analysis specific geoms (such as `geom_funnel()`) and quick plots for common visualizations. 83 | 84 | With tidy data, most data visualizations for meta-analyses are easy to build from the ground up. Nevertheless, `tidymeta` has several quick plot functions to make the process easier. `forest_plot()` takes a tidied meta-analysis and plots the effect sizes. 85 | 86 | ```{r} 87 | fp <- ma %>% 88 | forest_plot(group = group) 89 | 90 | fp 91 | ``` 92 | 93 | Because the results are still `ggplot2` objects, it's easy to make changes to the plot to your liking. 94 | 95 | ```{r} 96 | fp <- fp + 97 | scale_x_log() + 98 | theme(axis.text.y = element_text(face = c("bold", rep("plain", 21)))) 99 | 100 | fp 101 | ``` 102 | 103 | `tidymeta` currently supports forest plots, funnel plots, influence plots, and cumulative plots. 104 | 105 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | [![Travis build 5 | status](https://travis-ci.org/malcolmbarrett/tidymeta.svg?branch=master)](https://travis-ci.org/malcolmbarrett/tidymeta) 6 | 7 | # tidymeta 8 | 9 | Tidy and plot meta-analyses from popular meta-analytic tools in R. 10 | Currently in early development. 11 | 12 | ## Installation 13 | 14 | `tidymeta` requires the development version of several packages, 15 | including `ggplot2`, to function correctly. You can install the required 16 | packages for this vignette with the following code: 17 | 18 | ``` r 19 | install.packages(c("devtools", "yaml", "ggrepel")) 20 | library(devtools) 21 | install_github("r-lib/rlang") 22 | install_github("malcolmbarrett/tidymeta") 23 | install_github("malcolmbarrett/mbmisc") 24 | install_github("tidyverse/ggplot2") 25 | ``` 26 | 27 | # Tidy Meta-Analysis 28 | 29 | `tidymeta` is a toolkit for working with meta-analyses in R. Currently, 30 | it includes a data set, called `iud_cxca`, for a meta-analysis of the 31 | relationship between IUD use and cervical cancer. 32 | 33 | ``` r 34 | library(tidymeta) 35 | library(ggplot2) 36 | library(dplyr) 37 | library(broom) 38 | 39 | iud_cxca 40 | #> # A tibble: 16 x 26 41 | #> study_id study_name author es l95 u95 lnes lnl95 lnu95 42 | #> 43 | #> 1 1 Roura, 2016 Roura 0.600 0.300 1.20 -0.511 -1.20 0.182 44 | #> 2 2 Lassise, 1991 Lassi… 0.800 0.500 1.20 -0.223 -0.693 0.182 45 | #> 3 3 Li, 2000 Li 0.890 0.730 1.08 -0.117 -0.315 0.0770 46 | #> 4 4 Shields, 2004 Shiel… 0.500 0.300 0.820 -0.693 -1.20 -0.198 47 | #> 5 5 Castellsague… Caste… 0.630 0.380 1.06 -0.462 -0.968 0.0583 48 | #> 6 6 Castellsague… Caste… 0.450 0.300 0.670 -0.799 -1.20 -0.400 49 | #> 7 7 Brinton, 1990 Brint… 0.690 0.500 0.900 -0.371 -0.693 -0.105 50 | #> 8 8 Parazzini, 1… Paraz… 0.600 0.300 1.10 -0.511 -1.20 0.0953 51 | #> 9 9 Williams, 19… Willi… 1.00 0.600 1.60 0. -0.511 0.470 52 | #> 10 10 Hammouda, 20… Hammo… 0.300 0.100 0.500 -1.20 -2.30 -0.693 53 | #> 11 11 Castellsague… Caste… 1.08 0.370 3.20 0.0770 -0.994 1.16 54 | #> 12 12 Castellsague… Caste… 0.340 0.0500 2.56 -1.08 -3.00 0.940 55 | #> 13 13 Castellsague… Caste… 0.870 0.340 2.23 -0.139 -1.08 0.802 56 | #> 14 14 Castellsague… Caste… 0.490 0.190 1.23 -0.713 -1.66 0.207 57 | #> 15 15 Castellsague… Caste… 0.240 0.0900 0.660 -1.43 -2.41 -0.416 58 | #> 16 16 Celentano, 1… Celen… 0.500 0.170 1.47 -0.693 -1.77 0.385 59 | #> # ... with 17 more variables: selnes , group , case_num , 60 | #> # control_num , start_recruit , stop_recruit , 61 | #> # pub_year , numpap , ses , gravidity , 62 | #> # lifetimepart , coitarche , hpvstatus , smoking , 63 | #> # location , aair , hpvrate 64 | ``` 65 | 66 | `tidymeta` includes `broom` methods for cleaning meta-analysis results, 67 | although it currently only supports the `metafor` package. The `tidy()` 68 | function in `broom` puts results into a tidy data frame. 69 | 70 | ``` r 71 | library(metafor) 72 | #> Warning: package 'Matrix' was built under R version 3.4.4 73 | meta4 <- rma(yi = lnes, sei = selnes, data = iud_cxca) 74 | tidy(meta4) %>% 75 | as_tibble() # for space 76 | #> # A tibble: 17 x 8 77 | #> study type estimate std.error statistic p.value conf.low conf.high 78 | #> 79 | #> 1 1 study -0.511 0.354 -1.44 NA -1.20 0.182 80 | #> 2 2 study -0.223 0.223 -0.999 NA -0.661 0.215 81 | #> 3 3 study -0.117 0.0999 -1.17 NA -0.312 0.0793 82 | #> 4 4 study -0.693 0.257 -2.70 NA -1.20 -0.190 83 | #> 5 5 study -0.462 0.262 -1.77 NA -0.975 0.0509 84 | #> 6 6 study -0.799 0.205 -3.90 NA -1.20 -0.397 85 | #> 7 7 study -0.371 0.150 -2.47 NA -0.665 -0.0772 86 | #> 8 8 study -0.511 0.331 -1.54 NA -1.16 0.139 87 | #> 9 9 study 0. 0.250 0. NA -0.490 0.490 88 | #> 10 10 study -1.20 0.411 -2.93 NA -2.01 -0.399 89 | #> 11 11 study 0.0770 0.550 0.140 NA -1.00 1.16 90 | #> 12 12 study -1.08 1.00 -1.07 NA -3.05 0.889 91 | #> 13 13 study -0.139 0.480 -0.290 NA -1.08 0.801 92 | #> 14 14 study -0.713 0.476 -1.50 NA -1.65 0.221 93 | #> 15 15 study -1.43 0.508 -2.81 NA -2.42 -0.431 94 | #> 16 16 study -0.693 0.550 -1.26 NA -1.77 0.385 95 | #> 17 Overall summa… -0.449 0.0941 -4.77 1.83e-6 -0.634 -0.265 96 | ``` 97 | 98 | `tidymeta` also includes wrapper functions for working with 99 | meta-analysis packages in the context of the tidyverse. The main 100 | function for this is `meta_analysis()`, which models and tidies the 101 | object, as well as storing the results in the `meta` column to 102 | facilitate other analysis. 103 | 104 | ``` r 105 | # same as above but stores the meta-analysis object 106 | iud_cxca %>% 107 | meta_analysis(yi = lnes, sei = selnes, slab = study_name) 108 | #> # A tibble: 17 x 10 109 | #> study type estimate std.error statistic p.value conf.low conf.high 110 | #> 111 | #> 1 Roura, … study -0.511 0.354 -1.44 NA -1.20 0.182 112 | #> 2 Lassise… study -0.223 0.223 -0.999 NA -0.661 0.215 113 | #> 3 Li, 2000 study -0.117 0.0999 -1.17 NA -0.312 0.0793 114 | #> 4 Shields… study -0.693 0.257 -2.70 NA -1.20 -0.190 115 | #> 5 Castell… study -0.462 0.262 -1.77 NA -0.975 0.0509 116 | #> 6 Castell… study -0.799 0.205 -3.90 NA -1.20 -0.397 117 | #> 7 Brinton… study -0.371 0.150 -2.47 NA -0.665 -0.0772 118 | #> 8 Parazzi… study -0.511 0.331 -1.54 NA -1.16 0.139 119 | #> 9 William… study 0. 0.250 0. NA -0.490 0.490 120 | #> 10 Hammoud… study -1.20 0.411 -2.93 NA -2.01 -0.399 121 | #> 11 Castell… study 0.0770 0.550 0.140 NA -1.00 1.16 122 | #> 12 Castell… study -1.08 1.00 -1.07 NA -3.05 0.889 123 | #> 13 Castell… study -0.139 0.480 -0.290 NA -1.08 0.801 124 | #> 14 Castell… study -0.713 0.476 -1.50 NA -1.65 0.221 125 | #> 15 Castell… study -1.43 0.508 -2.81 NA -2.42 -0.431 126 | #> 16 Celenta… study -0.693 0.550 -1.26 NA -1.77 0.385 127 | #> 17 Overall summ… -0.449 0.0941 -4.77 1.83e-6 -0.634 -0.265 128 | #> # ... with 2 more variables: meta , weight 129 | ``` 130 | 131 | `tidymeta` doesn’t actually do meta-analysis; it unifies existing tools 132 | with the tidyverse. The benefit of this approach is that you can do 133 | meta-analyses with tidy tools in mind. For example, if you want to 134 | conduct a sub-group analysis, you can use the `group_by()` function from 135 | `dplyr`. Here, `group` is a variable with information about study 136 | design. 137 | 138 | ``` r 139 | ma <- iud_cxca %>% 140 | group_by(group) %>% 141 | meta_analysis(yi = lnes, sei = selnes, slab = study_name, exponentiate = TRUE) 142 | 143 | ma 144 | #> # A tibble: 21 x 11 145 | #> group study type estimate std.error statistic p.value conf.low 146 | #> 147 | #> 1 Nested … Roura, 2… study 0.600 0.354 -1.44 NA 0.300 148 | #> 2 Nested … Subgroup… summ… 0.600 0.354 -1.44 0.149 0.300 149 | #> 3 Populat… Lassise,… study 0.800 0.223 -0.999 NA 0.516 150 | #> 4 Populat… Li, 2000 study 0.890 0.0999 -1.17 NA 0.732 151 | #> 5 Populat… Shields,… study 0.500 0.257 -2.70 NA 0.302 152 | #> 6 Populat… Castells… study 0.630 0.262 -1.77 NA 0.377 153 | #> 7 Populat… Castells… study 0.450 0.205 -3.90 NA 0.301 154 | #> 8 Populat… Subgroup… summ… 0.655 0.146 -2.90 0.00374 0.492 155 | #> 9 Clinic-… Brinton,… study 0.690 0.150 -2.47 NA 0.514 156 | #> 10 Clinic-… Parazzin… study 0.600 0.331 -1.54 NA 0.313 157 | #> # ... with 11 more rows, and 3 more variables: conf.high , 158 | #> # meta , weight 159 | ``` 160 | 161 | You can also do sensitivy analyses and cumulative analyses with 162 | `sensitivity()` and `cumulative()`. 163 | 164 | # Visualization for Meta-Analysis 165 | 166 | `tidymeta` includes functionality for working with results in `ggplot2`, 167 | including meta-analysis specific geoms (such as `geom_funnel()`) and 168 | quick plots for common visualizations. 169 | 170 | With tidy data, most data visualizations for meta-analyses are easy to 171 | build from the ground up. Nevertheless, `tidymeta` has several quick 172 | plot functions to make the process easier. `forest_plot()` takes a 173 | tidied meta-analysis and plots the effect sizes. 174 | 175 | ``` r 176 | fp <- ma %>% 177 | forest_plot(group = group) 178 | 179 | fp 180 | ``` 181 | 182 | 183 | 184 | Because the results are still `ggplot2` objects, it’s easy to make 185 | changes to the plot to your liking. 186 | 187 | ``` r 188 | fp <- fp + 189 | scale_x_log() + 190 | theme(axis.text.y = element_text(face = c("bold", rep("plain", 21)))) 191 | 192 | fp 193 | ``` 194 | 195 | 196 | 197 | `tidymeta` currently supports forest plots, funnel plots, influence 198 | plots, and cumulative plots. 199 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | # DO NOT CHANGE the "init" and "install" sections below 2 | 3 | # Download script file from GitHub 4 | init: 5 | ps: | 6 | $ErrorActionPreference = "Stop" 7 | Invoke-WebRequest http://raw.github.com/krlmlr/r-appveyor/master/scripts/appveyor-tool.ps1 -OutFile "..\appveyor-tool.ps1" 8 | Import-Module '..\appveyor-tool.ps1' 9 | 10 | install: 11 | ps: Bootstrap 12 | 13 | cache: 14 | - C:\RLibrary 15 | 16 | # Adapt as necessary starting from here 17 | 18 | build_script: 19 | - travis-tool.sh install_deps 20 | 21 | test_script: 22 | - travis-tool.sh run_tests 23 | 24 | on_failure: 25 | - 7z a failure.zip *.Rcheck\* 26 | - appveyor PushArtifact failure.zip 27 | 28 | artifacts: 29 | - path: '*.Rcheck\**\*.log' 30 | name: Logs 31 | 32 | - path: '*.Rcheck\**\*.out' 33 | name: Logs 34 | 35 | - path: '*.Rcheck\**\*.fail' 36 | name: Logs 37 | 38 | - path: '*.Rcheck\**\*.Rout' 39 | name: Logs 40 | 41 | - path: '\*_*.tar.gz' 42 | name: Bits 43 | 44 | - path: '\*_*.zip' 45 | name: Bits 46 | 47 | environment: 48 | USE_RTOOLS: true 49 | -------------------------------------------------------------------------------- /data-raw/iud_cxca.csv: -------------------------------------------------------------------------------- 1 | study_id,study_name,author,es,l95,u95,lnes,lnl95,lnu95,selnes,group,case_num,control_num,start_recruit,stop_recruit,pub_year,numpap,ses,gravidity,lifetimepart,coitarche,hpvstatus,smoking,location,aair,hpvrate 2 | 1,"Roura, 2016",Roura,0.6000000238418579,0.30000001192092896,1.2000000476837158,-0.5108255840295616,-1.2039727645895069,0.18232159653038368,0.35364652069384966,Nested in cohort,134,264,1992,2006,2016,0,1,1,0,0,1,1,Europe,10.699999809265137,40.70000076293945 3 | 2,"Lassise, 1991",Lassise,0.800000011920929,0.5,1.2000000476837158,-0.22314353641304868,-0.6931471805599453,0.18232159653038368,0.2233338717067166,Population-based,479,789,1982,1984,1991,0,1,1,0,1,0,0,USA,15.300000190734863,6 4 | 3,"Li, 2000",Li,0.8899999856948853,0.7300000190734863,1.0800000429153442,-0.1165338323291143,-0.31471071871163714,0.07696108087255739,0.09991627540413126,Population-based,272,893,1989,1991,2e3,1,1,0,0,0,0,1,China,2.7799999713897705,7 5 | 4,"Shields, 2004",Shields,0.5,0.30000001192092896,0.8199999928474426,-0.6931471805599453,-1.2039727645895069,-0.19845094744646924,0.25651066763853,Population-based,235,486,1982,1984,2004,0,0,0,0,0,0,0,USA,15.300000190734863,NA 6 | 5,"Castellsague, 2011 (Spain)",Castellsagué,0.6299999952316284,0.3799999952316284,1.059999942779541,-0.4620354671654025,-0.967584038810052,0.05826885414240924,0.2616971665695054,Population-based,480,472,1985,1987,2011,1,1,0,0,1,1,0,Spain,6,15.600000381469727 7 | 6,"Castellsague, 2011 (Colombia)",Castellsagué,0.44999998807907104,0.30000001192092896,0.6700000166893005,-0.7985077227087252,-1.2039727645895069,-0.4004775416877218,0.20497327114841457,Population-based,448,452,1985,1988,2011,1,1,0,0,1,1,0,Colombia,48.20000076293945,15.600000381469727 8 | 7,"Brinton, 1990",Brinton,0.6899999976158142,0.5,0.8999999761581421,-0.3710636848461737,-0.6931471805599453,-0.10536054214877988,0.14994557102325648,Clinic-based,568,1071,1986,1987,1990,0,1,0,1,1,1,0,Latin America,30,NA 9 | 8,"Parazzini, 1992",Parazzini,0.6000000238418579,0.30000001192092896,1.100000023841858,-0.5108255840295616,-1.2039727645895069,0.0953102014787409,0.33144973624189994,Clinic-based,720,820,1990,1990,1992,1,1,1,1,1,0,1,Italy,7.900000095367432,15 10 | 9,"Williams, 1994",Williams,1,0.6000000238418579,1.600000023841858,0,-0.5108255840295616,0.47000364414689666,0.2502115378001169,Clinic-based,112,749,1981,1988,1994,0,0,0,1,0,0,0,Kenya,45,NA 11 | 10,"Hammouda, 2005",Hammouda,0.30000001192092896,0.10000000149011612,0.5,-1.2039727645895069,-2.3025850780928847,-0.6931471805599453,0.41057089222779064,Clinic-based,198,202,1997,1999,2005,0,1,0,1,0,1,0,Algeria,10.899999618530273,10.5 12 | 11,"Castellsague, 2011 (Morocco)",Castellsagué,1.0800000429153442,0.3700000047683716,3.200000047683716,0.07696108087255739,-0.9942522604563763,1.1631508247068418,0.5503579298885761,Clinic-based,202,214,1991,1993,2011,1,1,0,0,1,1,0,Morocco,11,20.5 13 | 12,"Castellsague, 2011 (India)",Castellsagué,0.3400000035762787,0.05000000074505806,2.559999942779541,-1.0788096508534633,-2.99573225865283,0.940007236139729,1.004015177243,Clinic-based,76,60,1998,1999,2011,1,1,0,0,1,1,0,India,30,27.700000762939453 14 | 13,"Castellsague, 2011 (Thailand)",Castellsagué,0.8700000047683716,0.3400000035762787,2.2300000190734863,-0.1392620618526208,-1.0788096508534633,0.8020015940251602,0.47979878695883255,Clinic-based,348,385,1990,1993,2011,1,1,0,0,1,1,0,Thailand,18.5,15.699999809265137 15 | 14,"Castellsague, 2011 (Philippines)",Castellsagué,0.49000000953674316,0.1899999976158142,1.2300000190734863,-0.7133498684147238,-1.6607312193699972,0.20701418489122547,0.4764656643523527,Clinic-based,383,387,1991,1993,2011,1,1,0,0,1,1,0,Philippines,25,9.199999809265137 16 | 15,"Castellsague, 2011 (Peru)",Castellsagué,0.23999999463558197,0.09000000357627869,0.6600000262260437,-1.4271163779918878,-2.407945568915443,-0.41551540422523675,0.5082730011964812,Clinic-based,137,140,1996,1998,2011,1,1,0,0,1,1,0,Peru,40,17.700000762939453 17 | 16,"Celentano, 1987",Celentano,0.5,0.17000000178813934,1.4700000286102295,-0.6931471805599453,-1.7719568314134087,0.3852624202533859,0.550311033588468,Friend/Family,153,153,1982,1984,1987,1,0,0,0,1,0,1,USA,8,6 18 | -------------------------------------------------------------------------------- /data/iud_cxca.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malcolmbarrett/tidymeta/b9c8835e8d998b06a1374e7f07c2741e36af9912/data/iud_cxca.rda -------------------------------------------------------------------------------- /man/add.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/add.R 3 | \name{add} 4 | \alias{add} 5 | \alias{add_weights} 6 | \alias{add_residuals} 7 | \alias{add_rstandard} 8 | \alias{add_i2} 9 | \alias{add_h2} 10 | \alias{add_tau2} 11 | \alias{add_blups} 12 | \title{Add model values to a table of meta-analysis results} 13 | \usage{ 14 | add_weights(x, .meta = NULL, group = NULL) 15 | 16 | add_residuals(x, .meta = NULL) 17 | 18 | add_rstandard(x, .meta = NULL) 19 | 20 | add_i2(x, .meta = NULL) 21 | 22 | add_h2(x, .meta = NULL) 23 | 24 | add_tau2(x, .meta = NULL) 25 | 26 | add_blups(x, .meta = NULL, exponentiate = FALSE) 27 | } 28 | \arguments{ 29 | \item{x}{a tidied meta-analysis} 30 | 31 | \item{.meta}{a meta-analysis object. If not \code{NULL}, then looks for a \code{meta} 32 | column in \code{x} containing an overall meta-analysis} 33 | 34 | \item{group}{a grouping variable} 35 | 36 | \item{exponentiate}{logical. Should the results be exponentiated?} 37 | } 38 | \value{ 39 | a \code{tbl} 40 | } 41 | \description{ 42 | \code{add_weights()} adds study weights to the model. \code{add_residuals()} and 43 | \code{add_rstandard()} add residuals. \code{add_i2()}, \code{add_h2()}, \code{add_tau2()} 44 | } 45 | \examples{ 46 | 47 | library(dplyr) 48 | 49 | iud_cxca \%>\% 50 | group_by(group) \%>\% 51 | meta_analysis(, yi = lnes, sei = selnes, slab = study_name) \%>\% 52 | add_i2() 53 | 54 | } 55 | -------------------------------------------------------------------------------- /man/add_meta.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/meta_analysis.R 3 | \name{add_meta} 4 | \alias{add_meta} 5 | \title{Add a meta-analysis to a tbl} 6 | \usage{ 7 | add_meta(x, meta, ...) 8 | } 9 | \arguments{ 10 | \item{x}{a \code{data.frame} produced by \code{tidy()}} 11 | 12 | \item{meta}{a meta-analysis object (e.g. \code{rma.uni})} 13 | 14 | \item{...}{additional arguments to \code{as.tbl}} 15 | } 16 | \value{ 17 | a \code{tbl} with a \code{listcol}, \code{meta}, containing the meta-analysis 18 | } 19 | \description{ 20 | \code{add_meta()} add a meta-analysis object to a tidied meta-analysis. 21 | } 22 | \examples{ 23 | 24 | library(metafor) 25 | library(broom) 26 | 27 | ma <- rma(yi = lnes, sei = selnes, slab = study_name, data = iud_cxca) 28 | 29 | ma \%>\% 30 | tidy() \%>\% 31 | add_meta(ma) 32 | 33 | } 34 | -------------------------------------------------------------------------------- /man/augmenters.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/augment.R 3 | \name{augment.rma.uni} 4 | \alias{augment.rma.uni} 5 | \title{Augment data with values from a meta-analysis model} 6 | \usage{ 7 | augment.rma.uni(x, ...) 8 | } 9 | \arguments{ 10 | \item{x}{a meta-analysis object. Currently supports \code{rma.uni} from the 11 | \code{metafor} package.} 12 | 13 | \item{...}{additional arguments} 14 | } 15 | \value{ 16 | a \code{data.frame} 17 | } 18 | \description{ 19 | Augment the original data with model residuals, fitted values, and influence 20 | statistics. 21 | } 22 | \examples{ 23 | 24 | library(broom) 25 | library(metafor) 26 | rma(yi = lnes, sei = selnes, slab = study_name, data = iud_cxca) \%>\% 27 | augment() 28 | 29 | } 30 | -------------------------------------------------------------------------------- /man/cumulative.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/influence.R 3 | \name{cumulative} 4 | \alias{cumulative} 5 | \title{Cumulative sensitivity analyses of meta-analysis results} 6 | \usage{ 7 | cumulative(x, prefix = "cumul_", conf.int = TRUE, exponentiate = FALSE, 8 | glance = FALSE, .f = metafor::cumul, ...) 9 | } 10 | \arguments{ 11 | \item{x}{a \code{tbl} produced by \code{\link[=meta_analysis]{meta_analysis()}} or by \code{\link[broom:tidy]{broom::tidy()}}} 12 | 13 | \item{prefix}{the prefix for the model result variables, e.g. estimate.} 14 | 15 | \item{conf.int}{logical. Should confidence intervals be included? Default is 16 | \code{TRUE}.} 17 | 18 | \item{exponentiate}{logical. Should results be exponentiated? Default is 19 | \code{FALSE}.} 20 | 21 | \item{glance}{logical. Should sensitivity model fit statistics be included? 22 | Default is \code{FALSE}.} 23 | 24 | \item{.f}{a function for sensitivity analysis. Default is \link[metafor:cumul]{metafor::cumul}} 25 | 26 | \item{...}{additional arguments} 27 | } 28 | \value{ 29 | a \code{tbl} 30 | } 31 | \description{ 32 | Conduct cumulative sensitivity analyses of meta-analysis results by adding 33 | studies in one at a time. \code{cumulative} works well with \code{\link[dplyr:arrange]{dplyr::arrange()}}. 34 | } 35 | \examples{ 36 | 37 | library(dplyr) 38 | 39 | meta_analysis(iud_cxca, yi = lnes, sei = selnes, slab = study_name) \%>\% 40 | arrange(desc(weight)) \%>\% 41 | cumulative() 42 | 43 | } 44 | -------------------------------------------------------------------------------- /man/figures/README-unnamed-chunk-1-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malcolmbarrett/tidymeta/b9c8835e8d998b06a1374e7f07c2741e36af9912/man/figures/README-unnamed-chunk-1-1.png -------------------------------------------------------------------------------- /man/figures/README-unnamed-chunk-6-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malcolmbarrett/tidymeta/b9c8835e8d998b06a1374e7f07c2741e36af9912/man/figures/README-unnamed-chunk-6-1.png -------------------------------------------------------------------------------- /man/figures/README-unnamed-chunk-7-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malcolmbarrett/tidymeta/b9c8835e8d998b06a1374e7f07c2741e36af9912/man/figures/README-unnamed-chunk-7-1.png -------------------------------------------------------------------------------- /man/geom_funnel.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/geom_funnel.R 3 | \name{geom_funnel} 4 | \alias{geom_funnel} 5 | \title{Funnel plot lines} 6 | \usage{ 7 | geom_funnel(mapping = NULL, data = NULL, ci_level = 0.95, 8 | log_summary = FALSE, colour = "black", color = NULL, 9 | position = "identity", na.rm = FALSE, 10 | summary_label = "Summary\\nEstimate", ci_label = NULL, show.legend = NA, 11 | inherit.aes = TRUE, ...) 12 | } 13 | \arguments{ 14 | \item{mapping}{Set of aesthetic mappings created by \code{\link[=aes]{aes()}} or 15 | \code{\link[=aes_]{aes_()}}. If specified and \code{inherit.aes = TRUE} (the 16 | default), it is combined with the default mapping at the top level of the 17 | plot. You must supply \code{mapping} if there is no plot mapping.} 18 | 19 | \item{data}{The data to be displayed in this layer. There are three 20 | options: 21 | 22 | If \code{NULL}, the default, the data is inherited from the plot 23 | data as specified in the call to \code{\link[=ggplot]{ggplot()}}. 24 | 25 | A \code{data.frame}, or other object, will override the plot 26 | data. All objects will be fortified to produce a data frame. See 27 | \code{\link[=fortify]{fortify()}} for which variables will be created. 28 | 29 | A \code{function} will be called with a single argument, 30 | the plot data. The return value must be a \code{data.frame.}, and 31 | will be used as the layer data.} 32 | 33 | \item{ci_level}{the confidence level desired for the psuedo-CI lines. Between 34 | 0 and 1. Also used for line labels.} 35 | 36 | \item{log_summary}{a summary estimate (see \code{\link[=pull_summary]{pull_summary()}})} 37 | 38 | \item{color, colour}{line color} 39 | 40 | \item{position}{Position adjustment, either as a string, or the result of 41 | a call to a position adjustment function.} 42 | 43 | \item{na.rm}{If \code{FALSE}, the default, missing values are removed with 44 | a warning. If \code{TRUE}, missing values are silently removed.} 45 | 46 | \item{summary_label}{a string. The legend label for the summary line.} 47 | 48 | \item{ci_label}{a string. The legend label for the CI lines. Default is 49 | \code{NULL}, in which case the labels will be created based on \code{ci_level}.} 50 | 51 | \item{show.legend}{logical. Should this layer be included in the legends? 52 | \code{NA}, the default, includes if any aesthetics are mapped. 53 | \code{FALSE} never includes, and \code{TRUE} always includes. 54 | It can also be a named logical vector to finely select the aesthetics to 55 | display.} 56 | 57 | \item{inherit.aes}{If \code{FALSE}, overrides the default aesthetics, 58 | rather than combining with them. This is most useful for helper functions 59 | that define both data and aesthetics and shouldn't inherit behaviour from 60 | the default plot specification, e.g. \code{\link[=borders]{borders()}}.} 61 | 62 | \item{...}{other arguments passed on to \code{\link[=layer]{layer()}}. These are 63 | often aesthetics, used to set an aesthetic to a fixed value, like 64 | \code{color = "red"} or \code{size = 3}. They may also be parameters 65 | to the paired geom/stat.} 66 | } 67 | \description{ 68 | `geom_funnel()`` computes psuedo confidence limits for the summary estimate 69 | of a meta-analysis to be used in a funnel plot. 70 | } 71 | \examples{ 72 | 73 | library(ggplot2) 74 | 75 | ma <- meta_analysis(iud_cxca, yi = lnes, sei = selnes, slab = study_name) 76 | 77 | ggplot(ma, aes(x = estimate, y = std.error)) + 78 | geom_point() + 79 | geom_funnel(aes(summary = pull_summary(ma))) + 80 | scale_y_reverse() 81 | 82 | } 83 | -------------------------------------------------------------------------------- /man/glance.rma.uni.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/glance.R 3 | \name{glance.rma.uni} 4 | \alias{glance.rma.uni} 5 | \title{Construct a one-row summary of meta-analysis model fit statistics.} 6 | \usage{ 7 | glance.rma.uni(x, ...) 8 | } 9 | \arguments{ 10 | \item{x}{a meta-analysis object. Currently supports \code{rma.uni} from the 11 | \code{metafor} package.} 12 | 13 | \item{...}{additional arguments} 14 | } 15 | \value{ 16 | a \code{data.frame} 17 | } 18 | \description{ 19 | \code{glance()} computes a one-row summary of meta-analysis objects, 20 | including estimates of heterogenity and model fit. 21 | } 22 | \examples{ 23 | 24 | library(broom) 25 | library(metafor) 26 | rma(yi = lnes, sei = selnes, slab = study_name, data = iud_cxca) \%>\% 27 | glance() 28 | 29 | } 30 | -------------------------------------------------------------------------------- /man/iud_cxca.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data.R 3 | \docType{data} 4 | \name{iud_cxca} 5 | \alias{iud_cxca} 6 | \title{Meta-analysis of IUD and cervical cancer} 7 | \format{A \code{tbl} with variables about both study esimates and study methods, 8 | including variables controlled, study design, and publication year.} 9 | \source{ 10 | Cortessis, V. K., Barrett, M., Brown Wade, N., Enebish, T., Perrigo, 11 | J., Tobin, J., Zhong, C., Zink, J.,Isiaka, V., Muderspach, L., Natavio, M., 12 | & McKean-Cowdin, R. (2017). “Intrauterine device use and risk of cervical 13 | cancer: a systematic review and meta-analysis.” Obstetrics and Gynecology: 14 | 130 (6). 15 | } 16 | \usage{ 17 | iud_cxca 18 | } 19 | \description{ 20 | This is data from a meta-analysis of the effect of Intrauterine Device use on 21 | cervical cancer. Estimates are odds ratios for ever-use of IUD. 22 | } 23 | \keyword{datasets} 24 | -------------------------------------------------------------------------------- /man/lock_order.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/quick_plots.R 3 | \name{lock_order} 4 | \alias{lock_order} 5 | \title{Lock the order of the data in the plot} 6 | \usage{ 7 | lock_order(var, rev = TRUE) 8 | } 9 | \arguments{ 10 | \item{var}{a variable to lock} 11 | 12 | \item{rev}{logical. Should the order be reversed to make it appear on the 13 | plot as in the data? Default is \code{TRUE}.} 14 | } 15 | \value{ 16 | a factor 17 | } 18 | \description{ 19 | \code{lock_order()} locks the order of the of an axis variable exactly as it 20 | appears in the data, rather than from the bottom up (for factors and 21 | numerics) or in alphabetical order (for characters). 22 | } 23 | \examples{ 24 | 25 | library(ggplot2) 26 | 27 | meta_analysis(iud_cxca, yi = lnes, sei = selnes, slab = study_name) \%>\% 28 | ggplot(aes(x = estimate, y = lock_order(study))) + 29 | geom_point() 30 | } 31 | -------------------------------------------------------------------------------- /man/log_scales.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/geom_funnel.R 3 | \name{scale_x_log} 4 | \alias{scale_x_log} 5 | \alias{scale_y_log} 6 | \title{Log scales for continuous data (x & y)} 7 | \usage{ 8 | scale_x_log(..., breaks = scales::log_breaks()) 9 | 10 | scale_y_log(..., breaks = scales::log_breaks()) 11 | } 12 | \arguments{ 13 | \item{...}{additional arguments passed to \code{scale_*_continuous()}} 14 | 15 | \item{breaks}{a vector of axis breaks} 16 | } 17 | \description{ 18 | Log scales for continuous data (x & y) 19 | } 20 | -------------------------------------------------------------------------------- /man/meta_analysis.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/meta_analysis.R 3 | \name{meta_analysis} 4 | \alias{meta_analysis} 5 | \title{Meta-Analysis} 6 | \usage{ 7 | meta_analysis(.data, .f = metafor::rma, ..., conf.int = TRUE, 8 | exponentiate = FALSE, include_studies = TRUE, bind_data = FALSE, 9 | weights = TRUE) 10 | } 11 | \arguments{ 12 | \item{.data}{a \code{data.frame} containing the data for the meta-analysis} 13 | 14 | \item{.f}{a meta-analysis function. Default is \link[metafor:rma]{metafor::rma}} 15 | 16 | \item{...}{additional arguments passed to \code{.f}} 17 | 18 | \item{conf.int}{logical. Include confidence intervals?} 19 | 20 | \item{exponentiate}{logical. Should the estimates and (if \code{conf.int} = 21 | \code{TRUE}) confidence intervals be exponentiated?} 22 | 23 | \item{include_studies}{logical. Include indidiual study coefficients?} 24 | 25 | \item{bind_data}{logical. Bind original data to output?} 26 | 27 | \item{weights}{logical. Include study weights in output?} 28 | } 29 | \value{ 30 | a \code{tbl} 31 | } 32 | \description{ 33 | A wrapper for meta-analytic functions that automatically tidies it and adds 34 | the meta-analysis object to the \code{tbl} in a \code{listcol}. 35 | } 36 | \examples{ 37 | 38 | meta_analysis(iud_cxca, yi = lnes, sei = selnes, slab = study_name) 39 | 40 | } 41 | -------------------------------------------------------------------------------- /man/metathemes.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/themes.R 3 | \name{theme_meta} 4 | \alias{theme_meta} 5 | \alias{theme_forest} 6 | \title{Minimalist theme with meta-analyses in mind} 7 | \usage{ 8 | theme_meta(font_size = 14, font_family = "", line_size = 0.5) 9 | 10 | theme_forest(font_size = 14, font_family = "", line_size = 0.5) 11 | } 12 | \arguments{ 13 | \item{font_size}{font size} 14 | 15 | \item{font_family}{font family} 16 | 17 | \item{line_size}{line size} 18 | } 19 | \description{ 20 | \code{theme_meta()} is a base theme, while \code{theme_forest()} has forest plots in 21 | mind, meaning it removes most legends and sets squares and diamonds as the 22 | default point shapes. 23 | } 24 | -------------------------------------------------------------------------------- /man/pipe.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/utils-pipe.R 3 | \name{\%>\%} 4 | \alias{\%>\%} 5 | \title{Pipe operator} 6 | \usage{ 7 | lhs \%>\% rhs 8 | } 9 | \description{ 10 | See \code{magrittr::\link[magrittr]{\%>\%}} for details. 11 | } 12 | \keyword{internal} 13 | -------------------------------------------------------------------------------- /man/pull_meta.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/meta_analysis.R 3 | \name{pull_meta} 4 | \alias{pull_meta} 5 | \title{Pull the meta-analysis object} 6 | \usage{ 7 | pull_meta(x) 8 | } 9 | \arguments{ 10 | \item{x}{a tidied meta-analysis} 11 | } 12 | \value{ 13 | an object created by a meta-analysis 14 | } 15 | \description{ 16 | Pull the meta-analysis object 17 | } 18 | \examples{ 19 | 20 | meta_analysis(iud_cxca, yi = lnes, sei = selnes, slab = study_name) \%>\% 21 | pull_meta() 22 | } 23 | -------------------------------------------------------------------------------- /man/pull_summary.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/meta_analysis.R 3 | \name{pull_summary} 4 | \alias{pull_summary} 5 | \title{Pull the meta-analysis summary estimate} 6 | \usage{ 7 | pull_summary(x, conf.int = FALSE) 8 | } 9 | \arguments{ 10 | \item{x}{a tidied meta-analysis} 11 | 12 | \item{conf.int}{logical. Include confidence intervals?} 13 | } 14 | \value{ 15 | an object created by a meta-analysis 16 | } 17 | \description{ 18 | Pull the meta-analysis summary estimate 19 | } 20 | \examples{ 21 | 22 | meta_analysis(iud_cxca, yi = lnes, sei = selnes, slab = study_name) \%>\% 23 | pull_summary() 24 | 25 | } 26 | -------------------------------------------------------------------------------- /man/quickplots.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/quick_plots.R 3 | \name{forest_plot} 4 | \alias{forest_plot} 5 | \alias{influence_plot} 6 | \alias{cumulative_plot} 7 | \alias{funnel_plot} 8 | \title{Quickly plot common visualizations for meta-analyses} 9 | \usage{ 10 | forest_plot(x, estimate = estimate, study = study, size = weight, 11 | shape = type, col = type, xmin = conf.low, xmax = conf.high, 12 | group = NULL, alpha = 0.75, height = 0, ...) 13 | 14 | influence_plot(x, estimate = l1o_estimate, study = study, size = 4, 15 | shape = 15, col = type, xmin = l1o_conf.low, xmax = l1o_conf.high, 16 | group = NULL, alpha = 0.75, height = 0, sum_lines = TRUE, ...) 17 | 18 | cumulative_plot(x, estimate = cumul_estimate, study = study, size = 4, 19 | shape = 15, col = type, xmin = cumul_conf.low, xmax = cumul_conf.high, 20 | group = NULL, alpha = 0.75, height = 0, sum_lines = TRUE, ...) 21 | 22 | funnel_plot(x, estimate = estimate, std.error = std.error, size = 3, 23 | shape = NULL, col = NULL, alpha = 0.75, reverse_y = TRUE, 24 | log_summary = FALSE, ...) 25 | } 26 | \arguments{ 27 | \item{x}{a tidied meta-analysis} 28 | 29 | \item{estimate}{variable name of point estimates} 30 | 31 | \item{study}{variable name of study labels} 32 | 33 | \item{size}{point size; either an aesthetic variable or a specific shape.} 34 | 35 | \item{shape}{shape of the points; either an aesthetic variable or a specific 36 | shape.} 37 | 38 | \item{col}{color of the points and lines; either an aesthetic variable or a 39 | specific color.} 40 | 41 | \item{xmin}{lower confidence interval variable name} 42 | 43 | \item{xmax}{upper confidence interval variable name} 44 | 45 | \item{group}{a grouping variable} 46 | 47 | \item{alpha}{transparancy level} 48 | 49 | \item{height}{line height for error bars} 50 | 51 | \item{...}{additional arguments} 52 | 53 | \item{sum_lines}{logical. Should vertical lines demarcating the summary 54 | estimate and confidence intervals be included?} 55 | 56 | \item{std.error}{variable name of standard error variable} 57 | 58 | \item{reverse_y}{logical. Should the y-axis be reversed?} 59 | 60 | \item{log_summary}{logical. Should the estimate and confidence intervals be 61 | log-transformed?} 62 | } 63 | \value{ 64 | a \code{ggplot2} object 65 | } 66 | \description{ 67 | \code{forest_plot()} presents study and summary estimates. \code{influence_plot()} 68 | shows the forest plot of senstivity analyses using \code{senstivity()}. 69 | \code{cumulative_plot()} shows the forest plot for \code{cumulative()}. \code{funnel_plot()} 70 | plots standard errors against the summary esitimate to assess publication 71 | bias. 72 | } 73 | \examples{ 74 | 75 | library(dplyr) 76 | 77 | ma <- iud_cxca \%>\% 78 | group_by(group) \%>\% 79 | meta_analysis(yi = lnes, sei = selnes, slab = study_name) 80 | 81 | forest_plot(ma) 82 | 83 | funnel_plot(ma) 84 | 85 | ma \%>\% 86 | sensitivity() \%>\% 87 | influence_plot() 88 | 89 | ma \%>\% 90 | cumulative() \%>\% 91 | cumulative_plot() 92 | 93 | } 94 | -------------------------------------------------------------------------------- /man/sensitivity.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/influence.R 3 | \name{sensitivity} 4 | \alias{sensitivity} 5 | \title{Sensitivity analyses of meta-analysis results} 6 | \usage{ 7 | sensitivity(x, type = "leave1out", prefix = "l1o_", conf.int = TRUE, 8 | exponentiate = FALSE, glance = FALSE, .f = metafor::leave1out, ...) 9 | } 10 | \arguments{ 11 | \item{x}{a \code{tbl} produced by \code{\link[=meta_analysis]{meta_analysis()}} or by \code{\link[broom:tidy]{broom::tidy()}}} 12 | 13 | \item{type}{type of sensitvity analysis.} 14 | 15 | \item{prefix}{the prefix for the model result variables, e.g. estimate.} 16 | 17 | \item{conf.int}{logical. Should confidence intervals be included? Default is 18 | \code{TRUE}.} 19 | 20 | \item{exponentiate}{logical. Should results be exponentiated? Default is 21 | \code{FALSE}.} 22 | 23 | \item{glance}{logical. Should sensitivity model fit statistics be included? 24 | Default is \code{FALSE}.} 25 | 26 | \item{.f}{a function for sensitivity analysis. Default is 27 | \link[metafor:leave1out]{metafor::leave1out}} 28 | 29 | \item{...}{additional arguments} 30 | } 31 | \value{ 32 | a \code{tbl} 33 | } 34 | \description{ 35 | Conduct leave-one-out or group-wise sensitivity analyses of meta-analysis 36 | results. 37 | } 38 | \examples{ 39 | 40 | meta_analysis(iud_cxca, yi = lnes, sei = selnes, slab = study_name) \%>\% 41 | sensitivity() 42 | 43 | } 44 | -------------------------------------------------------------------------------- /man/sub2summary.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/quick_plots.R 3 | \name{sub2summary} 4 | \alias{sub2summary} 5 | \title{Group summary estimates together} 6 | \usage{ 7 | sub2summary(x, group, ...) 8 | } 9 | \arguments{ 10 | \item{x}{a tidied meta-analysis} 11 | 12 | \item{group}{a grouping variable} 13 | 14 | \item{...}{additional arguments} 15 | } 16 | \value{ 17 | a \code{tbl} 18 | } 19 | \description{ 20 | The default in \code{tidymeta} is to put subgroup estimates in the same group as 21 | the estimates; \code{sub2summary()} gives them a value of "Overall", which groups 22 | all summaries together. 23 | } 24 | \examples{ 25 | 26 | library(dplyr) 27 | 28 | iud_cxca \%>\% 29 | group_by(group) \%>\% 30 | meta_analysis(yi = lnes, sei = selnes, slab = study_name) \%>\% 31 | sub2summary(group) 32 | 33 | } 34 | -------------------------------------------------------------------------------- /man/text_table.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/text_table.R 3 | \name{text_table} 4 | \alias{text_table} 5 | \title{Quickly produce text tables to accompany forest plots.} 6 | \usage{ 7 | text_table(.data, ..., study = study, group = NULL, show_y_facets = TRUE, 8 | show_y_axis = TRUE, show_grid = FALSE, size = 3.75) 9 | } 10 | \arguments{ 11 | \item{.data}{a \code{data.frame}} 12 | 13 | \item{...}{bare variable names to include in the table} 14 | 15 | \item{study}{name of study variable} 16 | 17 | \item{group}{a grouping variable} 18 | 19 | \item{show_y_facets}{logical. Should y-axis facets be included if grouped?} 20 | 21 | \item{show_y_axis}{logical. Should study names be included on y-axis?} 22 | 23 | \item{show_grid}{logical. Show grid lines?} 24 | 25 | \item{size}{text size} 26 | } 27 | \value{ 28 | a \code{ggplot2} object 29 | } 30 | \description{ 31 | Quickly produce text tables to accompany forest plots. 32 | } 33 | \examples{ 34 | 35 | meta_analysis(iud_cxca, yi = lnes, sei = selnes, slab = study_name) \%>\% 36 | text_table(weight) 37 | 38 | } 39 | -------------------------------------------------------------------------------- /man/tidiers.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/tidy.R 3 | \name{tidy.rma.uni} 4 | \alias{tidy.rma.uni} 5 | \title{Tidying methods for meta-analyis objects} 6 | \usage{ 7 | tidy.rma.uni(x, conf.int = TRUE, exponentiate = FALSE, 8 | include_studies = TRUE, measure = "GEN", ...) 9 | } 10 | \arguments{ 11 | \item{x}{a meta-analysis object. Currently supports \code{rma.uni} from the 12 | \code{metafor} package.} 13 | 14 | \item{conf.int}{logical. Include confidence intervals?} 15 | 16 | \item{exponentiate}{logical. Should the estimates and (if \code{conf.int} = 17 | \code{TRUE}) confidence intervals be exponentiated?} 18 | 19 | \item{include_studies}{logical. Should individual studies be included in the 20 | output?} 21 | 22 | \item{measure}{measure type. See \code{\link[metafor:rma]{metafor::rma()}}} 23 | 24 | \item{...}{additional arguments} 25 | } 26 | \value{ 27 | a \code{data.frame} 28 | } 29 | \description{ 30 | These methods tidy the results of meta-analysis objects 31 | } 32 | \examples{ 33 | library(broom) 34 | library(metafor) 35 | rma(yi = lnes, sei = selnes, slab = study_name, data = iud_cxca) \%>\% 36 | tidy() 37 | 38 | } 39 | -------------------------------------------------------------------------------- /tidymeta.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: Default 4 | SaveWorkspace: Default 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: knitr 13 | LaTeX: XeLaTeX 14 | 15 | AutoAppendNewline: Yes 16 | StripTrailingWhitespace: Yes 17 | 18 | BuildType: Package 19 | PackageUseDevtools: Yes 20 | PackageInstallArgs: --no-multiarch --with-keep.source 21 | PackageRoxygenize: rd,collate,namespace 22 | --------------------------------------------------------------------------------