├── .Rbuildignore ├── .gitignore ├── .travis.yml ├── CODE_OF_CONDUCT.md ├── DESCRIPTION ├── LICENSE ├── LICENSE.md ├── NAMESPACE ├── R ├── ci_to_se.R ├── dat_bakermans_kranenburg.R ├── dat_keech.R ├── dat_ooi.R ├── firepower.R ├── mapower_se.R └── mapower_ul.R ├── README.Rmd ├── README.md ├── README_files └── figure-gfm │ ├── unnamed-chunk-2-1.png │ ├── unnamed-chunk-3-1.png │ ├── unnamed-chunk-4-1.png │ └── unnamed-chunk-5-1.png ├── _pkgdown.yml ├── data ├── dat_bakermans_kranenburg.rda ├── dat_keech.rda └── dat_ooi.rda ├── inst └── CITATION ├── man ├── ci_to_se.Rd ├── dat_bakermans_kranenburg.Rd ├── dat_keech.Rd ├── dat_ooi.Rd ├── firepower.Rd ├── mapower_se.Rd └── mapower_ul.Rd ├── metameta.Rproj ├── tests ├── testthat.R └── testthat │ └── test_misc_firepower.R └── vignettes ├── .gitignore └── introduction.Rmd /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^_pkgdown\.yml$ 2 | ^docs$ 3 | ^pkgdown$ 4 | ^\.travis\.yml$ 5 | ^.*\.Rproj$ 6 | ^\.Rproj\.user$ 7 | ^LICENSE\.md$ 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # History files 2 | .Rhistory 3 | .Rapp.history 4 | 5 | # Session Data files 6 | .RData 7 | 8 | # User-specific files 9 | .Ruserdata 10 | 11 | # Example code in package build process 12 | *-Ex.R 13 | 14 | # Output files from R CMD build 15 | /*.tar.gz 16 | 17 | # Output files from R CMD check 18 | /*.Rcheck/ 19 | 20 | # RStudio files 21 | .Rproj.user/ 22 | 23 | # produced vignettes 24 | vignettes/*.html 25 | vignettes/*.pdf 26 | 27 | # OAuth2 token, see https://github.com/hadley/httr/releases/tag/v0.3 28 | .httr-oauth 29 | 30 | # knitr and R markdown default cache directories 31 | *_cache/ 32 | /cache/ 33 | 34 | # Temporary files created by R markdown 35 | *.utf8.md 36 | *.knit.md 37 | 38 | # R Environment Variables 39 | .Renviron 40 | docs 41 | 42 | .DS_Store 43 | inst/doc 44 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # R for travis: see documentation at https://docs.travis-ci.com/user/languages/r 2 | 3 | language: R 4 | cache: packages 5 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at daniel.quintana@medisin.uio.no. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: metameta 2 | Type: Package 3 | Title: A Suite of Tools for calculating and visualising study-level statistical power for meta-analyses 4 | Version: 0.2 5 | Authors@R: person("Daniel S.", "Quintana", email = "daniel.quintana@psykologi.uio.no", role = c("aut", "cre")) 6 | Description: A Suite of Tools for calculating and visualising study-level statistical power for meta-analyses 7 | License: MIT + file LICENSE 8 | URL: https://github.com/dsquintana/metameta 9 | Encoding: UTF-8 10 | LazyData: true 11 | Depends: R (>= 3.5.0) 12 | Imports: 13 | ggplot2, 14 | dplyr, 15 | tidyr, 16 | ggthemes 17 | Suggests: 18 | testthat, 19 | knitr, 20 | rmarkdown 21 | RoxygenNote: 7.2.0 22 | VignetteBuilder: knitr 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | YEAR: 2022 2 | COPYRIGHT HOLDER: metameta authors 3 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # MIT License 2 | 3 | Copyright (c) 2022 metameta authors 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 | exportPattern("^[[:alpha:]]+") 2 | -------------------------------------------------------------------------------- /R/ci_to_se.R: -------------------------------------------------------------------------------- 1 | #' Calculate standard error based on confidence intervals 2 | #' 3 | #' @param lower A lower confidence interval bound 4 | #' @param upper An upper confidence interval bound 5 | #' @return A standard error value 6 | #' @examples 7 | #' ci_to_se(-0.12, 1.71) 8 | #' ci_to_se(0.07, 1.12) 9 | 10 | 11 | ci_to_se <- function(lower, upper) { 12 | se <- ((upper) - (lower)) / (2 * 1.96) 13 | } 14 | -------------------------------------------------------------------------------- /R/dat_bakermans_kranenburg.R: -------------------------------------------------------------------------------- 1 | #' Studies on the impact of intranasal oxytocin in clinical groups 2 | #' 3 | #' This is data from a meta-analysis on 19 studies investigating the impact of intranasal oxytocin 4 | #' administration on various clinical-related outcomes in clinical groups. Postive effect size values 5 | #' are indicative of a positive effect of intranasal oxytocin on outcomes. Effect size 6 | #' measure confidence intervals, and standard errors were extracted from Figure 2 of the 7 | #' article (see reference below). 8 | #' 9 | #' 10 | #' @format A data frame with 19 rows and 5 columns: 11 | #' \describe{ 12 | #' \item{study}{The name of the first author of the study and the year it was published} 13 | #' \item{yi}{Effect size measure (Cohen's d)} 14 | #' \item{sei}{The standard error} 15 | #' ... 16 | #' } 17 | # 18 | #' @references{ 19 | #' Bakermans-Kranenburg MJ, van I Jzendoorn MH. Sniffing around oxytocin: review and 20 | #' meta-analyses of trials in healthy and clinical groups with implications for 21 | #' pharmacotherapy. 22 | #' \emph{Translational Psychiatry}, \bold{3}, e258. 23 | #' } 24 | #'@examples 25 | #'power_bakermans_kranenburg <- 26 | #' mapower_se( 27 | #' dat = dat_bakermans_kranenburg, 28 | #' observed_es = 0.32, 29 | #' name = "Bakermans-Kranenburg et al 2013" 30 | #' ) 31 | #' 32 | "dat_bakermans_kranenburg" 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /R/dat_keech.R: -------------------------------------------------------------------------------- 1 | #' Studies on the impact of intranasal oxytocin on emotion recognition in neurodevelopmental disorders 2 | #' 3 | #' This is data from a meta-analysis on 12 studies investigating the impact of intranasal oxytocin 4 | #' administration on emotion recognition in neurodevelopmental disorders. Postive effect size values 5 | #' are indicative of a positive effect of intranasal oxytocin on emotion recognition. Effect size 6 | #' measure and confidence intervals were extracted from Figure 2 of the article (see reference below). 7 | #' 8 | #' 9 | #' @format A data frame with 13 rows and 3 columns: 10 | #' \describe{ 11 | #' \item{study}{The name of the first author of the study and the year it was published} 12 | #' \item{yi}{Effect size measure (Hedges' g)} 13 | #' \item{lower}{The lower bound of a 95\% confidence interval} 14 | #' \item{upper}{The upper bound of a 95\% confidence interval} 15 | #' ... 16 | #' } 17 | #' 18 | #' @references{ 19 | #' Keech, B., Crowe, S., & Hocking, D. R. (2018). Intranasal oxytocin, 20 | #' social cognition and neurodevelopmental disorders: a meta-analysis 21 | #' \emph{Psychoneuroendocrinology}, \bold{87}, 9--19. 22 | #' } 23 | #'@examples 24 | #'power_keech <- 25 | #' mapower_ul( 26 | #' dat = dat_keech, 27 | #' observed_es = 0.08, 28 | #' name = "Keech et al 2018" 29 | #' ) 30 | "dat_keech" 31 | -------------------------------------------------------------------------------- /R/dat_ooi.R: -------------------------------------------------------------------------------- 1 | #' Studies on the impact of intranasal oxytocin on social cognition in autism spectrum disorders 2 | #' 3 | #' This is data from a meta-analysis on 9 studies investigating the impact of intranasal oxytocin 4 | #' administration on social cognition in autism spectrum disorders. Postive effect size values 5 | #' are indicative of a positive effect of intranasal oxytocin on social cognition. Effect size 6 | #' measure and confidence intervals were extracted from Figure 2 of the article (see reference below). 7 | #' 8 | #' 9 | #' @format A data frame with 9 rows and 3 columns: 10 | #' \describe{ 11 | #' \item{study}{The name of the first author of the study and the year it was published} 12 | #' \item{yi}{Effect size measure (Hedges' g)} 13 | #' \item{sei}{The standard error} 14 | #' ... 15 | #' } 16 | # 17 | #' @references{ 18 | #' Ooi YP, Weng SJ, Kossowsky J, Gerger H, Sung M. (2017). Oxytocin and Autism Spectrum Disorders: 19 | #' A Systematic Review and Meta-Analysis of Randomized Controlled Trials. 20 | #' \emph{Pharmacopsychiatry}, \bold{50}, 5--13. 21 | #' } 22 | #'@examples 23 | #'power_ooi <- 24 | #' mapower_se( 25 | #' dat = dat_ooi, 26 | #' observed_es = 0.178, 27 | #' name = "Ooi et al 2017" 28 | #' ) 29 | "dat_ooi" 30 | -------------------------------------------------------------------------------- /R/firepower.R: -------------------------------------------------------------------------------- 1 | #' Calculate the median study power for a meta-analysis and visualise this data using a Firepower plot 2 | #' 3 | #' Creates a dataset with median power and a firepower plot, which visualises the median power for a 4 | #' meta-analysis assuming the observed effect size in the meta-analysis is the true effect size and assuming a 5 | #' range of true effect sizes ranging from 0.1 to 1 in increments of 0.1. See 'Details'. 6 | #' 7 | #' \strong{The true effect size} 8 | #' 9 | #' For the purposes of power analysis a "true" effect size needs to be specified. However, 10 | #' the true effect size is unknown when testing hypotheses and reported summary 11 | #' effect sizes are typically inflated. Thus, Firepower plots implements two alternative 12 | #' categories for a true effect for the purposes of power 13 | #' analysis: The observed summary effect size estimate reported in the meta-analysis and statistical power for 14 | #' a range of true effect sizes, The default "medium" range is from 0.1 to 1, in increments of 0.1. 15 | #' However, a "small" and "large" range is also available (see the "size" argument below for details). 16 | #' 17 | #' @param power_list A list of dataframes with calculated power, derived from the "mapower_ul" or "mapower_se" 18 | #' functions. See 'Examples' for how to make a list. 19 | #' @param size The effect size range, as specified using the mapower_se() or mapower_ul() functions, 20 | #' which created the 'power_list' dataframe or dataframes. 21 | #' The default is a medium range is 0.1 to 1, in increments of 0.1. 22 | #' Other options include a "small" range (0.05 to 0.5 in increments of 0.05) and a "large" 23 | #' range (0.25 to 2.5 in increments of 0.25). 24 | #' @param es An optional string for the name of the effect size for the plot (e.g., "Hedges g"). 25 | #' The default string is "Effect size". 26 | #' @return This function returns the following: 27 | #' \item{dat}{A dataset with the median results from power analyses for a range of effect sizes, including the 28 | #' specified true effect size, in a column labelled "power_true". The additional added columns include 29 | #' results for power analysis assuming a range of true effect sizes, with the default beginning at 0.1 ("power_es01"), 30 | #' then 0.2 ("power_es02"), then continuing in increments of 0.1 up to 1 ("power_es1"). A 31 | #' "small" and "large" effect size range is also possible (see the 'size' argument 32 | #' for details)} 33 | #' \item{fp_plot}{A firepower plot} 34 | #' @examples 35 | #' ### Calcuate median power for meta-analyses 36 | #' power_ooi <- mapower_se(dat = dat_ooi, observed_es = 0.178, name = "ooi et al 2017") 37 | #' power_med_ooi <- power_ooi$power_median_dat 38 | #' 39 | #' keech_power <- mapower_ul(dat = dat_keech, observed_es = 0.08, name = "Keech et al 2017") 40 | #' power_med_keech <- keech_power$power_median_dat 41 | #' 42 | #' power_bakermans_kranenburg <- mapower_se(dat = dat_bakermans_kranenburg, observed_es = 0.32, name = "Bakermans-Kranenburg et al 2013") 43 | #' power_med_bakermans_kranenburg <- power_bakermans_kranenburg$power_median_dat 44 | #' 45 | #' ### Create a list 46 | #' list_power <- list(power_med_ooi, power_med_keech, power_med_bakermans_kranenburg) 47 | #' 48 | #' ### Run firepower function 49 | #' fp <- firepower(list_power) 50 | #' 51 | #' ### Extract data from datasets in list 52 | #' power_dat <- fp$dat 53 | #' power_dat 54 | #' 55 | #' ### Create firepower plot 56 | #' fp_plot <- fp$fp_plot 57 | #' fp_plot 58 | #' 59 | 60 | 61 | 62 | 63 | firepower <- function(power_list, 64 | size = "medium", 65 | es = "Effect size"){ 66 | #'@import ggplot2 67 | #'@import tidyr 68 | 69 | if(size == "small"){ 70 | firepower_list <- lapply(power_list, function(x) x[, 71 | c("es_observed", 72 | "es005", "es01", 73 | "es015", "es02", 74 | "es025", "es03", 75 | "es035", "es04", 76 | "es045", "es05", 77 | "meta_analysis_name" 78 | )]) 79 | 80 | firepower_dat_wide <- do.call(rbind.data.frame, firepower_list) 81 | firepower_dat_wide 82 | power_med_dat_long <- tidyr::gather(firepower_dat_wide, 83 | effect, power, es_observed:es05, 84 | factor_key=TRUE) 85 | power_med_dat_long$es_cat <- 86 | ifelse(power_med_dat_long$effect == "es_observed", 87 | c("observed_es"), 88 | c("range_es")) 89 | power_med_dat_long 90 | firepower_plot <- ggplot2::ggplot(data = power_med_dat_long) + 91 | ggplot2::geom_tile(ggplot2::aes( 92 | x = effect, 93 | y = meta_analysis_name, 94 | fill = power 95 | )) + 96 | ggplot2::theme(aspect.ratio = 0.3) + 97 | ggplot2::scale_fill_gradient2( 98 | name = "Power", 99 | midpoint = 0.5, 100 | low = "white", 101 | mid = "orange", 102 | high = "red" 103 | ) + 104 | ggplot2::facet_grid( ~ es_cat, scale = 'free_x', space = "free_x") + 105 | ggthemes::theme_tufte(base_family = "sans") 106 | 107 | firepower_plot <- 108 | firepower_plot + ggplot2::theme(strip.text.x = ggplot2::element_blank()) 109 | firepower_plot <- firepower_plot + ggplot2::labs(x = es, y = "") 110 | firepower_plot <- 111 | firepower_plot + ggplot2::scale_x_discrete( 112 | labels = c( 113 | "es_observed" = "Observed", 114 | "es005" = "0.05", 115 | "es01" = "0.1", 116 | "es015" = "0.15", 117 | "es02" = "0.2", 118 | "es025" = "0.25", 119 | "es03" = "0.3", 120 | "es035" = "0.35", 121 | "es04" = "0.4", 122 | "es045" = "0.45", 123 | "es05" = "0.5" 124 | )) 125 | plot <- firepower_plot 126 | plot 127 | 128 | } else { 129 | if(size == "medium"){ 130 | firepower_list<- lapply(power_list, function(x) x[, 131 | c("es_observed", 132 | "es01", "es02", 133 | "es03", "es04", 134 | "es05", "es06", 135 | "es07", "es08", 136 | "es09", "es1", 137 | "meta_analysis_name" 138 | )]) 139 | 140 | firepower_dat_wide <- do.call(rbind.data.frame, firepower_list) 141 | firepower_dat_wide 142 | power_med_dat_long <- tidyr::gather(firepower_dat_wide, 143 | effect, power, es_observed:es1, 144 | factor_key=TRUE) 145 | power_med_dat_long$es_cat <- 146 | ifelse(power_med_dat_long$effect == "es_observed", 147 | c("observed_es"), 148 | c("range_es")) 149 | power_med_dat_long 150 | firepower_plot <- ggplot2::ggplot(data = power_med_dat_long) + 151 | ggplot2::geom_tile(ggplot2::aes( 152 | x = effect, 153 | y = meta_analysis_name, 154 | fill = power 155 | )) + 156 | ggplot2::theme(aspect.ratio = 0.3) + 157 | ggplot2::scale_fill_gradient2( 158 | name = "Power", 159 | midpoint = 0.5, 160 | low = "white", 161 | mid = "orange", 162 | high = "red" 163 | ) + 164 | ggplot2::facet_grid( ~ es_cat, scale = 'free_x', space = "free_x") + 165 | ggthemes::theme_tufte(base_family = "sans") 166 | 167 | firepower_plot <- 168 | firepower_plot + ggplot2::theme(strip.text.x = ggplot2::element_blank()) 169 | firepower_plot <- firepower_plot + ggplot2::labs(x = es, y = "") 170 | firepower_plot <- 171 | firepower_plot + ggplot2::scale_x_discrete( 172 | labels = c( 173 | "es_observed" = "Observed", 174 | "es01" = "0.1", 175 | "es02" = "0.2", 176 | "es03" = "0.3", 177 | "es04" = "0.4", 178 | "es05" = "0.5", 179 | "es06" = "0.6", 180 | "es07" = "0.7", 181 | "es08" = "0.8", 182 | "es09" = "0.9", 183 | "es1" = "1" 184 | )) 185 | plot <- firepower_plot 186 | plot 187 | 188 | } else { 189 | if(size == "large"){ 190 | firepower_list<- lapply(power_list, function(x) x[, 191 | c("es_observed", 192 | "es025", "es05", 193 | "es075", "es1", 194 | "es125", "es15", 195 | "es175", "es2", 196 | "es225", "es25", 197 | "meta_analysis_name" 198 | )]) 199 | 200 | firepower_dat_wide <- do.call(rbind.data.frame, firepower_list) 201 | firepower_dat_wide 202 | power_med_dat_long <- tidyr::gather(firepower_dat_wide, 203 | effect, power, es_observed:es25, 204 | factor_key=TRUE) 205 | power_med_dat_long$es_cat <- 206 | ifelse(power_med_dat_long$effect == "es_observed", 207 | c("observed_es"), 208 | c("range_es")) 209 | power_med_dat_long 210 | firepower_plot <- ggplot2::ggplot(data = power_med_dat_long) + 211 | ggplot2::geom_tile(ggplot2::aes( 212 | x = effect, 213 | y = meta_analysis_name, 214 | fill = power 215 | )) + 216 | ggplot2::theme(aspect.ratio = 0.3) + 217 | ggplot2::scale_fill_gradient2( 218 | name = "Power", 219 | midpoint = 0.5, 220 | low = "white", 221 | mid = "orange", 222 | high = "red" 223 | ) + 224 | ggplot2::facet_grid( ~ es_cat, scale = 'free_x', space = "free_x") + 225 | ggthemes::theme_tufte(base_family = "sans") 226 | 227 | firepower_plot <- 228 | firepower_plot + ggplot2::theme(strip.text.x = ggplot2::element_blank()) 229 | firepower_plot <- firepower_plot + ggplot2::labs(x = es, y = "") 230 | firepower_plot <- 231 | firepower_plot + ggplot2::scale_x_discrete( 232 | labels = c( 233 | "es_observed" = "Observed", 234 | "es025" = "0.25", 235 | "es05" = "0.5", 236 | "es075" = "0.75", 237 | "es1" = "1", 238 | "es125" = "1.25", 239 | "es15" = "1.5", 240 | "es175" = "1.75", 241 | "es2" = "2", 242 | "es225" = "2.25", 243 | "es25" = "2.5" 244 | )) 245 | plot <- firepower_plot 246 | plot 247 | 248 | } 249 | } 250 | } 251 | 252 | value <- list( 253 | fp_plot = plot, 254 | dat = firepower_dat_wide 255 | ) # Create a list of output objects 256 | attr(value, "class") <- "firepower" 257 | value 258 | } 259 | -------------------------------------------------------------------------------- /R/mapower_se.R: -------------------------------------------------------------------------------- 1 | #' Calculate statistical power using effect size and standard error data 2 | #' 3 | #' Calculate statistical power using effect size and standard error data that 4 | #' is typically reported in meta-analyses. Power is calculated assuming 5 | #' the summary effect size in a meta-analysis is true effect size and assuming a 6 | #' range of effect sizes. The script to calculate power 7 | #' was adapted from the "viz_sunset" function of the metaviz package. 8 | #' 9 | #' \strong{The true effect size} 10 | #' 11 | #' For the purposes of power analysis a "true" effect size needs to be specified. However, 12 | #' the true effect size is unknown when testing hypotheses and reported summary 13 | #' effect sizes are typically inflated. Here, the observed summary effect size estimate 14 | #' reported in the meta-analysis results is used as one possible true effect size, however, 15 | #' other effect sizes can be specified here instead. Additionally, statistical power for a range 16 | #' of true effect sizes are returned. The default is a "medium" range from 0.1 to 1, 17 | #' in increments of 0.1. However, a "small" and "large" range is also available 18 | #' (see the "size" argument below for details). 19 | #' 20 | #' @param dat A dataset that contains one column with observed effect sizes or outcomes 21 | #' labelled "yi" and a column with standard error data, labelled "sei". 22 | #' @param size The effect size range. The default is a medium range (0.1 to 1, in increments of 0.1). 23 | #' In other words, if you do not use this argument, the medium range will be used. 24 | #' Other options include a "small" range (0.05 to 0.5 in increments of 0.05) and a "large" 25 | #' range (0.25 to 2.5 in increments of 0.25). 26 | #' @param observed_es The observed summary effect size estimate for the meta-analysis, which is one output 27 | #' for the set of possible "true" effect sizes. See 'Details' 28 | #' @param name A label with a name for the meta-analysis, which is required for using the "firepower" function. 29 | #' See 'Examples' 30 | #' @return This function returns the following: 31 | #' \item{dat}{A dataset with results from power analyses for a range of effect sizes, including the 32 | #' specified observed effect size, in a column labelled "es_observed". The additional added columns include 33 | #' results for power analysis assuming a range of true effect sizes, with the default beginning at 0.1 ("power_es01"), 34 | #' then 0.2 ("power_es02"), then continuing in increments of 0.1 up to 1 ("power_es1"). A smaller 35 | #' or larger range of effect sizes can be specified (see the 'size' argument for details)} 36 | #' @examples 37 | #' ### An analysis using the default effect size range 38 | #' 39 | #' power_ooi <- mapower_se( 40 | #' dat = dat_ooi, 41 | #' observed_es = 0.178, 42 | #' name = "ooi et al 2017") 43 | #' power_ooi 44 | #' 45 | #' ### An analysis using the large effect size range 46 | #' 47 | #' power_ooi_l <- mapower_se( 48 | #' dat = dat_ooi, 49 | #' size = "large", 50 | #' observed_es = 0.178, 51 | #' name = "ooi et al 2017") 52 | #' power_ooi_l 53 | #' 54 | #' ### An analysis using the small effect size range 55 | #' 56 | #' power_ooi_s <- mapower_se( 57 | #' dat = dat_ooi, 58 | #' size = "small", 59 | #' observed_es = 0.178, 60 | #' name = "ooi et al 2017") 61 | #' power_ooi_s 62 | #' 63 | 64 | mapower_se <- 65 | function(dat, 66 | size = "medium", 67 | observed_es, 68 | name) 69 | #'@import dplyr 70 | { 71 | if(size == "small"){ 72 | dat[["power_es_observed"]] <- 73 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 74 | abs(observed_es), dat[["sei"]])) + 75 | stats::pnorm(stats::qnorm(0.05 / 2) * 76 | dat[["sei"]], abs(observed_es), 77 | dat[["sei"]]) # Calculate power for each study for observed effect 78 | dat[["power_es005"]] <- 79 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 80 | abs(0.05), dat[["sei"]])) + 81 | stats::pnorm(stats::qnorm(0.05 / 2) * 82 | dat[["sei"]], abs(0.05), 83 | dat[["sei"]]) # Calculate power for each study for an effect of 0.05 84 | dat[["power_es01"]] <- 85 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 86 | abs(0.1), dat[["sei"]])) + 87 | stats::pnorm(stats::qnorm(0.05 / 2) * 88 | dat[["sei"]], abs(0.1), 89 | dat[["sei"]]) # Calculate power for each study for an effect of 0.1 90 | dat[["power_es015"]] <- 91 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 92 | abs(0.15), dat[["sei"]])) + 93 | stats::pnorm(stats::qnorm(0.05 / 2) * 94 | dat[["sei"]], abs(0.15), 95 | dat[["sei"]]) # Calculate power for each study for an effect of 0.15 96 | dat[["power_es02"]] <- 97 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 98 | abs(0.2), dat[["sei"]])) + 99 | stats::pnorm(stats::qnorm(0.05 / 2) * 100 | dat[["sei"]], abs(0.2), 101 | dat[["sei"]]) # Calculate power for each study for an effect of 0.2 102 | dat[["power_es025"]] <- 103 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 104 | abs(0.25), dat[["sei"]])) + 105 | stats::pnorm(stats::qnorm(0.05 / 2) * 106 | dat[["sei"]], abs(0.25), 107 | dat[["sei"]]) # Calculate power for each study for an effect of 0.25 108 | dat[["power_es03"]] <- 109 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 110 | abs(0.3), dat[["sei"]])) + 111 | stats::pnorm(stats::qnorm(0.05 / 2) * 112 | dat[["sei"]], abs(0.3), 113 | dat[["sei"]]) # Calculate power for each study for an effect of 0.3 114 | dat[["power_es035"]] <- 115 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 116 | abs(0.35), dat[["sei"]])) + 117 | stats::pnorm(stats::qnorm(0.05 / 2) * 118 | dat[["sei"]], abs(0.35), 119 | dat[["sei"]]) # Calculate power for each study for an effect of 0.35 120 | dat[["power_es04"]] <- 121 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 122 | abs(0.4), dat[["sei"]])) + 123 | stats::pnorm(stats::qnorm(0.05 / 2) * 124 | dat[["sei"]], abs(0.4), 125 | dat[["sei"]]) # Calculate power for each study for an effect of 0.4 126 | dat[["power_es045"]] <- 127 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 128 | abs(0.45), dat[["sei"]])) + 129 | stats::pnorm(stats::qnorm(0.05 / 2) * 130 | dat[["sei"]], abs(0.45), 131 | dat[["sei"]]) # Calculate power for each study for an effect of 0.45 132 | dat[["power_es05"]] <- 133 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 134 | abs(0.5), dat[["sei"]])) + 135 | stats::pnorm(stats::qnorm(0.05 / 2) * 136 | dat[["sei"]], abs(0.5), 137 | dat[["sei"]]) # Calculate power for each study for an effect of 0.5 138 | dat <- as.data.frame(dat) 139 | power_median_dat <- data.frame(power_es_observed=numeric(1), 140 | es005=numeric(1), 141 | es01=numeric(1), 142 | es015=numeric(1), 143 | es02=numeric(1), 144 | es025=numeric(1), 145 | es03=numeric(1), 146 | es035=numeric(1), 147 | es04=numeric(1), 148 | es045=numeric(1), 149 | es05=numeric(1) 150 | ) 151 | power_median_dat[["es_observed"]] <- median(dat[["power_es_observed"]]) 152 | power_median_dat[["es005"]] <- median(dat[["power_es005"]]) 153 | power_median_dat[["es01"]] <- median(dat[["power_es01"]]) 154 | power_median_dat[["es015"]] <- median(dat[["power_es015"]]) 155 | power_median_dat[["es02"]] <- median(dat[["power_es02"]]) 156 | power_median_dat[["es025"]] <- median(dat[["power_es025"]]) 157 | power_median_dat[["es03"]] <- median(dat[["power_es03"]]) 158 | power_median_dat[["es035"]] <- median(dat[["power_es035"]]) 159 | power_median_dat[["es04"]] <- median(dat[["power_es04"]]) 160 | power_median_dat[["es045"]] <- median(dat[["power_es045"]]) 161 | power_median_dat[["es05"]] <- median(dat[["power_es05"]]) 162 | power_median_dat <- as.data.frame(power_median_dat) 163 | power_median_dat <- dplyr::mutate(power_median_dat, 164 | meta_analysis_name = name) 165 | } else { 166 | if(size == "medium"){ 167 | dat[["power_es_observed"]] <- 168 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 169 | abs(observed_es), dat[["sei"]])) + 170 | stats::pnorm(stats::qnorm(0.05 / 2) * 171 | dat[["sei"]], abs(observed_es), 172 | dat[["sei"]]) # Calculate power for each study for observed effect 173 | dat[["power_es01"]] <- 174 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 175 | abs(0.1), dat[["sei"]])) + 176 | stats::pnorm(stats::qnorm(0.05 / 2) * 177 | dat[["sei"]], abs(0.1), 178 | dat[["sei"]]) # Calculate power for each study for an effect of 0.1 179 | dat[["power_es02"]] <- 180 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 181 | abs(0.2), dat[["sei"]])) + 182 | stats::pnorm(stats::qnorm(0.05 / 2) * 183 | dat[["sei"]], abs(0.2), 184 | dat[["sei"]]) # Calculate power for each study for an effect of 0.2 185 | dat[["power_es03"]] <- 186 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 187 | abs(0.30), dat[["sei"]])) + 188 | stats::pnorm(stats::qnorm(0.05 / 2) * 189 | dat[["sei"]], abs(0.30), 190 | dat[["sei"]]) # Calculate power for each study for an effect of 0.3 191 | dat[["power_es04"]] <- 192 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 193 | abs(0.40), dat[["sei"]])) + 194 | stats::pnorm(stats::qnorm(0.05 / 2) * 195 | dat[["sei"]], abs(0.40), 196 | dat[["sei"]]) # Calculate power for each study for an effect of 0.4 197 | dat[["power_es05"]] <- 198 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 199 | abs(0.50), dat[["sei"]])) + 200 | stats::pnorm(stats::qnorm(0.05 / 2) * 201 | dat[["sei"]], abs(0.50), 202 | dat[["sei"]]) # Calculate power for each study for an effect of 0.5 203 | dat[["power_es06"]] <- 204 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 205 | abs(0.60), dat[["sei"]])) + 206 | stats::pnorm(stats::qnorm(0.05 / 2) * 207 | dat[["sei"]], abs(0.60), 208 | dat[["sei"]]) # Calculate power for each study for an effect of 0.6 209 | dat[["power_es07"]] <- 210 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 211 | abs(0.70), dat[["sei"]])) + 212 | stats::pnorm(stats::qnorm(0.05 / 2) * 213 | dat[["sei"]], abs(0.70), 214 | dat[["sei"]]) # Calculate power for each study for an effect of 0.7 215 | dat[["power_es08"]] <- 216 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 217 | abs(0.80), dat[["sei"]])) + 218 | stats::pnorm(stats::qnorm(0.05 / 2) * 219 | dat[["sei"]], abs(0.80), 220 | dat[["sei"]]) # Calculate power for each study for an effect of 0.8 221 | dat[["power_es09"]] <- 222 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 223 | abs(0.90), dat[["sei"]])) + 224 | stats::pnorm(stats::qnorm(0.05 / 2) * 225 | dat[["sei"]], abs(0.90), 226 | dat[["sei"]]) # Calculate power for each study for an effect of 0.9 227 | dat[["power_es1"]] <- 228 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 229 | abs(1), dat[["sei"]])) + 230 | stats::pnorm(stats::qnorm(0.05 / 2) * 231 | dat[["sei"]], abs(1), 232 | dat[["sei"]]) # Calculate power for each study for an effect of 1 233 | dat <- as.data.frame(dat) 234 | power_median_dat <- data.frame(power_es_observed=numeric(1), 235 | es01=numeric(1), 236 | es02=numeric(1), 237 | es03=numeric(1), 238 | es04=numeric(1), 239 | es05=numeric(1), 240 | es06=numeric(1), 241 | es07=numeric(1), 242 | es08=numeric(1), 243 | es09=numeric(1), 244 | es1=numeric(1) 245 | 246 | ) 247 | power_median_dat[["es_observed"]] <- median(dat[["power_es_observed"]]) 248 | power_median_dat[["es01"]] <- median(dat[["power_es01"]]) 249 | power_median_dat[["es02"]] <- median(dat[["power_es02"]]) 250 | power_median_dat[["es03"]] <- median(dat[["power_es03"]]) 251 | power_median_dat[["es04"]] <- median(dat[["power_es04"]]) 252 | power_median_dat[["es05"]] <- median(dat[["power_es05"]]) 253 | power_median_dat[["es06"]] <- median(dat[["power_es06"]]) 254 | power_median_dat[["es07"]] <- median(dat[["power_es07"]]) 255 | power_median_dat[["es08"]] <- median(dat[["power_es08"]]) 256 | power_median_dat[["es09"]] <- median(dat[["power_es09"]]) 257 | power_median_dat[["es1"]] <- median(dat[["power_es1"]]) 258 | power_median_dat <- as.data.frame(power_median_dat) 259 | power_median_dat <- dplyr::mutate(power_median_dat, 260 | meta_analysis_name = name) 261 | } else { 262 | if(size == "large"){ 263 | dat[["power_es_observed"]] <- 264 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 265 | abs(observed_es), dat[["sei"]])) + 266 | stats::pnorm(stats::qnorm(0.05 / 2) * 267 | dat[["sei"]], abs(observed_es), 268 | dat[["sei"]]) # Calculate power for each study for observed effect 269 | dat[["power_es025"]] <- 270 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 271 | abs(0.25), dat[["sei"]])) + 272 | stats::pnorm(stats::qnorm(0.05 / 2) * 273 | dat[["sei"]], abs(0.25), 274 | dat[["sei"]]) # Calculate power for each study for an effect of 0.25 275 | dat[["power_es05"]] <- 276 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 277 | abs(0.5), dat[["sei"]])) + 278 | stats::pnorm(stats::qnorm(0.05 / 2) * 279 | dat[["sei"]], abs(0.5), 280 | dat[["sei"]]) # Calculate power for each study for an effect of 0.5 281 | dat[["power_es075"]] <- 282 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 283 | abs(0.75), dat[["sei"]])) + 284 | stats::pnorm(stats::qnorm(0.05 / 2) * 285 | dat[["sei"]], abs(0.75), 286 | dat[["sei"]]) # Calculate power for each study for an effect of 0.75 287 | dat[["power_es1"]] <- 288 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 289 | abs(1), dat[["sei"]])) + 290 | stats::pnorm(stats::qnorm(0.05 / 2) * 291 | dat[["sei"]], abs(1), 292 | dat[["sei"]]) # Calculate power for each study for an effect of 1 293 | dat[["power_es125"]] <- 294 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 295 | abs(1.25), dat[["sei"]])) + 296 | stats::pnorm(stats::qnorm(0.05 / 2) * 297 | dat[["sei"]], abs(1.25), 298 | dat[["sei"]]) # Calculate power for each study for an effect of 1.25 299 | dat[["power_es15"]] <- 300 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 301 | abs(1.5), dat[["sei"]])) + 302 | stats::pnorm(stats::qnorm(0.05 / 2) * 303 | dat[["sei"]], abs(1.5), 304 | dat[["sei"]]) # Calculate power for each study for an effect of 1.5 305 | dat[["power_es175"]] <- 306 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 307 | abs(1.75), dat[["sei"]])) + 308 | stats::pnorm(stats::qnorm(0.05 / 2) * 309 | dat[["sei"]], abs(1.75), 310 | dat[["sei"]]) # Calculate power for each study for an effect of 1.75 311 | dat[["power_es2"]] <- 312 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 313 | abs(2), dat[["sei"]])) + 314 | stats::pnorm(stats::qnorm(0.05 / 2) * 315 | dat[["sei"]], abs(2), 316 | dat[["sei"]]) # Calculate power for each study for an effect of 2 317 | dat[["power_es225"]] <- 318 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 319 | abs(2.25), dat[["sei"]])) + 320 | stats::pnorm(stats::qnorm(0.05 / 2) * 321 | dat[["sei"]], abs(2.25), 322 | dat[["sei"]]) # Calculate power for each study for an effect of 2.25 323 | dat[["power_es25"]] <- 324 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 325 | abs(2.5), dat[["sei"]])) + 326 | stats::pnorm(stats::qnorm(0.05 / 2) * 327 | dat[["sei"]], abs(2.5), 328 | dat[["sei"]]) # Calculate power for each study for an effect of 2.5 329 | dat <- as.data.frame(dat) 330 | power_median_dat <- data.frame(power_es_observed=numeric(1), 331 | es025=numeric(1), 332 | es05=numeric(1), 333 | es075=numeric(1), 334 | es1=numeric(1), 335 | es125=numeric(1), 336 | es15=numeric(1), 337 | es175=numeric(1), 338 | es2=numeric(1), 339 | es225=numeric(1), 340 | es25=numeric(1) 341 | 342 | ) 343 | power_median_dat[["es_observed"]] <- median(dat[["power_es_observed"]]) 344 | power_median_dat[["es025"]] <- median(dat[["power_es025"]]) 345 | power_median_dat[["es05"]] <- median(dat[["power_es05"]]) 346 | power_median_dat[["es075"]] <- median(dat[["power_es075"]]) 347 | power_median_dat[["es1"]] <- median(dat[["power_es1"]]) 348 | power_median_dat[["es125"]] <- median(dat[["power_es125"]]) 349 | power_median_dat[["es15"]] <- median(dat[["power_es15"]]) 350 | power_median_dat[["es175"]] <- median(dat[["power_es175"]]) 351 | power_median_dat[["es2"]] <- median(dat[["power_es2"]]) 352 | power_median_dat[["es225"]] <- median(dat[["power_es225"]]) 353 | power_median_dat[["es25"]] <- median(dat[["power_es25"]]) 354 | power_median_dat <- as.data.frame(power_median_dat) 355 | power_median_dat <- dplyr::mutate(power_median_dat, 356 | meta_analysis_name = name) 357 | } 358 | 359 | } 360 | } 361 | value <- list( 362 | dat = dat, 363 | power_median_dat = power_median_dat 364 | ) # Create a list of output objects 365 | attr(value, "class") <- "mapower_se_t2" 366 | value 367 | } 368 | -------------------------------------------------------------------------------- /R/mapower_ul.R: -------------------------------------------------------------------------------- 1 | #' Calculate statistical power using effect size and confidence interval data 2 | #' 3 | #' Calculate statistical power using effect size and confidence interval data that 4 | #' is typically reported in meta-analyses. Power is calculated assuming 5 | #' the true effect size and a range of effect sizes. The script to calculate power 6 | #' was adapted from the "viz_sunset" function of the metaviz package. 7 | #' 8 | #' \strong{The true effect size} 9 | #' 10 | #' For the purposes of power analysis a "true" effect size needs to be specified. However, 11 | #' the true effect size is unknown when testing hypotheses and reported summary 12 | #' effect sizes are typically inflated. Here, the observed summary effect size estimate 13 | #' reported in the meta-analysis results is used as one possible true effect size, however, 14 | #' other effect sizes can be specified here instead. Additionally, statistical power for a range 15 | #' of true effect sizes are returned. The default is a "medium" range from 0.1 to 1, 16 | #' in increments of 0.1. However, a "small" and "large" range is also available 17 | #' (see the "size" argument below for details). 18 | #' 19 | #' @param dat A dataset that contains one column with observed effect sizes or outcomes 20 | #' labelled "yi", a column labelled "lower" with the lower confidence 21 | #' interval bound, and column labelled "upper" with the upper confidence 22 | #' interval bound. This function assumes a 95\% confidence interval. 23 | #' @param size The effect size range. The default is a medium range (0.1 to 1, in increments of 0.1). 24 | #' In other words, if you do not use this argument, the medium range will be used. 25 | #' Other options include a "small" range (0.05 to 0.5 in increments of 0.05) and a "large" 26 | #' range (0.25 to 2.5 in increments of 0.25). 27 | #' @param observed_es The observed summary effect size estimate for the meta-analysis, which is one output 28 | #' for the set of possible "true" effect sizes. See 'Details' 29 | #' @param name A label with a name for the meta-analysis, which is required for using the "firepower" function. 30 | #' See 'Examples' 31 | #' @return This function returns the following: 32 | #' \item{dat}{A dataset with results from power analyses for a range of effect sizes, including the 33 | #' specified observed effect size, in a column labelled "es_observed". The additional added columns include 34 | #' results for power analysis assuming a range of true effect sizes, with the default beginning at 0.1 ("power_es01"), 35 | #' then 0.2 ("power_es02"), then continuing in increments of 0.1 up to 1 ("power_es1"). A smaller 36 | #' or larger range of effect sizes can be specified (see the 'size' argument for details)} 37 | #' @examples 38 | #' 39 | #' ### An analysis using the default effect size range 40 | #' 41 | #' keech_power <- mapower_ul( 42 | #' dat = dat_keech, 43 | #' observed_es = 0.08, 44 | #' name = "Keech et al 2017") 45 | #' keech_power 46 | #' 47 | #' ### An analysis using the large effect size range 48 | #' 49 | #' keech_power_l <- mapower_ul( 50 | #' dat = dat_keech, 51 | #' size = "large", 52 | #' observed_es = 0.08, 53 | #' name = "Keech et al 2017") 54 | #' keech_power_l 55 | #' 56 | #' ### An analysis using the small effect size range 57 | #' 58 | #' keech_power_s <- mapower_ul( 59 | #' dat = dat_keech, 60 | #' size = "small", 61 | #' observed_es = 0.08, 62 | #' name = "Keech et al 2017") 63 | #' keech_power_s 64 | #' 65 | 66 | 67 | mapower_ul <- 68 | function(dat, 69 | size = "medium", 70 | observed_es, 71 | name) 72 | #'@import dplyr 73 | { 74 | dat[["sei"]] <- ((dat[["upper"]]) - 75 | (dat[["lower"]])) / (2 * 1.96) # Calculate standard error if not already available 76 | if(size == "small"){ 77 | dat[["power_es_observed"]] <- 78 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 79 | abs(observed_es), dat[["sei"]])) + 80 | stats::pnorm(stats::qnorm(0.05 / 2) * 81 | dat[["sei"]], abs(observed_es), 82 | dat[["sei"]]) # Calculate power for each study for observed effect 83 | dat[["power_es005"]] <- 84 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 85 | abs(0.05), dat[["sei"]])) + 86 | stats::pnorm(stats::qnorm(0.05 / 2) * 87 | dat[["sei"]], abs(0.05), 88 | dat[["sei"]]) # Calculate power for each study for an effect of 0.05 89 | dat[["power_es01"]] <- 90 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 91 | abs(0.1), dat[["sei"]])) + 92 | stats::pnorm(stats::qnorm(0.05 / 2) * 93 | dat[["sei"]], abs(0.1), 94 | dat[["sei"]]) # Calculate power for each study for an effect of 0.1 95 | dat[["power_es015"]] <- 96 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 97 | abs(0.15), dat[["sei"]])) + 98 | stats::pnorm(stats::qnorm(0.05 / 2) * 99 | dat[["sei"]], abs(0.15), 100 | dat[["sei"]]) # Calculate power for each study for an effect of 0.15 101 | dat[["power_es02"]] <- 102 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 103 | abs(0.2), dat[["sei"]])) + 104 | stats::pnorm(stats::qnorm(0.05 / 2) * 105 | dat[["sei"]], abs(0.2), 106 | dat[["sei"]]) # Calculate power for each study for an effect of 0.2 107 | dat[["power_es025"]] <- 108 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 109 | abs(0.25), dat[["sei"]])) + 110 | stats::pnorm(stats::qnorm(0.05 / 2) * 111 | dat[["sei"]], abs(0.25), 112 | dat[["sei"]]) # Calculate power for each study for an effect of 0.25 113 | dat[["power_es03"]] <- 114 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 115 | abs(0.3), dat[["sei"]])) + 116 | stats::pnorm(stats::qnorm(0.05 / 2) * 117 | dat[["sei"]], abs(0.3), 118 | dat[["sei"]]) # Calculate power for each study for an effect of 0.3 119 | dat[["power_es035"]] <- 120 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 121 | abs(0.35), dat[["sei"]])) + 122 | stats::pnorm(stats::qnorm(0.05 / 2) * 123 | dat[["sei"]], abs(0.35), 124 | dat[["sei"]]) # Calculate power for each study for an effect of 0.35 125 | dat[["power_es04"]] <- 126 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 127 | abs(0.4), dat[["sei"]])) + 128 | stats::pnorm(stats::qnorm(0.05 / 2) * 129 | dat[["sei"]], abs(0.4), 130 | dat[["sei"]]) # Calculate power for each study for an effect of 0.4 131 | dat[["power_es045"]] <- 132 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 133 | abs(0.45), dat[["sei"]])) + 134 | stats::pnorm(stats::qnorm(0.05 / 2) * 135 | dat[["sei"]], abs(0.45), 136 | dat[["sei"]]) # Calculate power for each study for an effect of 0.45 137 | dat[["power_es05"]] <- 138 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 139 | abs(0.5), dat[["sei"]])) + 140 | stats::pnorm(stats::qnorm(0.05 / 2) * 141 | dat[["sei"]], abs(0.5), 142 | dat[["sei"]]) # Calculate power for each study for an effect of 0.5 143 | dat <- as.data.frame(dat) 144 | power_median_dat <- data.frame(power_es_observed=numeric(1), 145 | es005=numeric(1), 146 | es01=numeric(1), 147 | es015=numeric(1), 148 | es02=numeric(1), 149 | es025=numeric(1), 150 | es03=numeric(1), 151 | es035=numeric(1), 152 | es04=numeric(1), 153 | es045=numeric(1), 154 | es05=numeric(1) 155 | ) 156 | power_median_dat[["es_observed"]] <- median(dat[["power_es_observed"]]) 157 | power_median_dat[["es005"]] <- median(dat[["power_es005"]]) 158 | power_median_dat[["es01"]] <- median(dat[["power_es01"]]) 159 | power_median_dat[["es015"]] <- median(dat[["power_es015"]]) 160 | power_median_dat[["es02"]] <- median(dat[["power_es02"]]) 161 | power_median_dat[["es025"]] <- median(dat[["power_es025"]]) 162 | power_median_dat[["es03"]] <- median(dat[["power_es03"]]) 163 | power_median_dat[["es035"]] <- median(dat[["power_es035"]]) 164 | power_median_dat[["es04"]] <- median(dat[["power_es04"]]) 165 | power_median_dat[["es045"]] <- median(dat[["power_es045"]]) 166 | power_median_dat[["es05"]] <- median(dat[["power_es05"]]) 167 | power_median_dat <- as.data.frame(power_median_dat) 168 | power_median_dat <- dplyr::mutate(power_median_dat, 169 | meta_analysis_name = name) 170 | } else { 171 | if(size == "medium"){ 172 | dat[["power_es_observed"]] <- 173 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 174 | abs(observed_es), dat[["sei"]])) + 175 | stats::pnorm(stats::qnorm(0.05 / 2) * 176 | dat[["sei"]], abs(observed_es), 177 | dat[["sei"]]) # Calculate power for each study for observed effect 178 | dat[["power_es01"]] <- 179 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 180 | abs(0.1), dat[["sei"]])) + 181 | stats::pnorm(stats::qnorm(0.05 / 2) * 182 | dat[["sei"]], abs(0.1), 183 | dat[["sei"]]) # Calculate power for each study for an effect of 0.1 184 | dat[["power_es02"]] <- 185 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 186 | abs(0.2), dat[["sei"]])) + 187 | stats::pnorm(stats::qnorm(0.05 / 2) * 188 | dat[["sei"]], abs(0.2), 189 | dat[["sei"]]) # Calculate power for each study for an effect of 0.2 190 | dat[["power_es03"]] <- 191 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 192 | abs(0.30), dat[["sei"]])) + 193 | stats::pnorm(stats::qnorm(0.05 / 2) * 194 | dat[["sei"]], abs(0.30), 195 | dat[["sei"]]) # Calculate power for each study for an effect of 0.3 196 | dat[["power_es04"]] <- 197 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 198 | abs(0.40), dat[["sei"]])) + 199 | stats::pnorm(stats::qnorm(0.05 / 2) * 200 | dat[["sei"]], abs(0.40), 201 | dat[["sei"]]) # Calculate power for each study for an effect of 0.4 202 | dat[["power_es05"]] <- 203 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 204 | abs(0.50), dat[["sei"]])) + 205 | stats::pnorm(stats::qnorm(0.05 / 2) * 206 | dat[["sei"]], abs(0.50), 207 | dat[["sei"]]) # Calculate power for each study for an effect of 0.5 208 | dat[["power_es06"]] <- 209 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 210 | abs(0.60), dat[["sei"]])) + 211 | stats::pnorm(stats::qnorm(0.05 / 2) * 212 | dat[["sei"]], abs(0.60), 213 | dat[["sei"]]) # Calculate power for each study for an effect of 0.6 214 | dat[["power_es07"]] <- 215 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 216 | abs(0.70), dat[["sei"]])) + 217 | stats::pnorm(stats::qnorm(0.05 / 2) * 218 | dat[["sei"]], abs(0.70), 219 | dat[["sei"]]) # Calculate power for each study for an effect of 0.7 220 | dat[["power_es08"]] <- 221 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 222 | abs(0.80), dat[["sei"]])) + 223 | stats::pnorm(stats::qnorm(0.05 / 2) * 224 | dat[["sei"]], abs(0.80), 225 | dat[["sei"]]) # Calculate power for each study for an effect of 0.8 226 | dat[["power_es09"]] <- 227 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 228 | abs(0.90), dat[["sei"]])) + 229 | stats::pnorm(stats::qnorm(0.05 / 2) * 230 | dat[["sei"]], abs(0.90), 231 | dat[["sei"]]) # Calculate power for each study for an effect of 0.9 232 | dat[["power_es1"]] <- 233 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 234 | abs(1), dat[["sei"]])) + 235 | stats::pnorm(stats::qnorm(0.05 / 2) * 236 | dat[["sei"]], abs(1), 237 | dat[["sei"]]) # Calculate power for each study for an effect of 1 238 | dat <- as.data.frame(dat) 239 | power_median_dat <- data.frame(power_es_observed=numeric(1), 240 | es01=numeric(1), 241 | es02=numeric(1), 242 | es03=numeric(1), 243 | es04=numeric(1), 244 | es05=numeric(1), 245 | es06=numeric(1), 246 | es07=numeric(1), 247 | es08=numeric(1), 248 | es09=numeric(1), 249 | es1=numeric(1) 250 | 251 | ) 252 | power_median_dat[["es_observed"]] <- median(dat[["power_es_observed"]]) 253 | power_median_dat[["es01"]] <- median(dat[["power_es01"]]) 254 | power_median_dat[["es02"]] <- median(dat[["power_es02"]]) 255 | power_median_dat[["es03"]] <- median(dat[["power_es03"]]) 256 | power_median_dat[["es04"]] <- median(dat[["power_es04"]]) 257 | power_median_dat[["es05"]] <- median(dat[["power_es05"]]) 258 | power_median_dat[["es06"]] <- median(dat[["power_es06"]]) 259 | power_median_dat[["es07"]] <- median(dat[["power_es07"]]) 260 | power_median_dat[["es08"]] <- median(dat[["power_es08"]]) 261 | power_median_dat[["es09"]] <- median(dat[["power_es09"]]) 262 | power_median_dat[["es1"]] <- median(dat[["power_es1"]]) 263 | power_median_dat <- as.data.frame(power_median_dat) 264 | power_median_dat <- dplyr::mutate(power_median_dat, 265 | meta_analysis_name = name) 266 | } else { 267 | if(size == "large"){ 268 | dat[["power_es_observed"]] <- 269 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 270 | abs(observed_es), dat[["sei"]])) + 271 | stats::pnorm(stats::qnorm(0.05 / 2) * 272 | dat[["sei"]], abs(observed_es), 273 | dat[["sei"]]) # Calculate power for each study for observed effect 274 | dat[["power_es025"]] <- 275 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 276 | abs(0.25), dat[["sei"]])) + 277 | stats::pnorm(stats::qnorm(0.05 / 2) * 278 | dat[["sei"]], abs(0.25), 279 | dat[["sei"]]) # Calculate power for each study for an effect of 0.25 280 | dat[["power_es05"]] <- 281 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 282 | abs(0.5), dat[["sei"]])) + 283 | stats::pnorm(stats::qnorm(0.05 / 2) * 284 | dat[["sei"]], abs(0.5), 285 | dat[["sei"]]) # Calculate power for each study for an effect of 0.5 286 | dat[["power_es075"]] <- 287 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 288 | abs(0.75), dat[["sei"]])) + 289 | stats::pnorm(stats::qnorm(0.05 / 2) * 290 | dat[["sei"]], abs(0.75), 291 | dat[["sei"]]) # Calculate power for each study for an effect of 0.75 292 | dat[["power_es1"]] <- 293 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 294 | abs(1), dat[["sei"]])) + 295 | stats::pnorm(stats::qnorm(0.05 / 2) * 296 | dat[["sei"]], abs(1), 297 | dat[["sei"]]) # Calculate power for each study for an effect of 1 298 | dat[["power_es125"]] <- 299 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 300 | abs(1.25), dat[["sei"]])) + 301 | stats::pnorm(stats::qnorm(0.05 / 2) * 302 | dat[["sei"]], abs(1.25), 303 | dat[["sei"]]) # Calculate power for each study for an effect of 1.25 304 | dat[["power_es15"]] <- 305 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 306 | abs(1.5), dat[["sei"]])) + 307 | stats::pnorm(stats::qnorm(0.05 / 2) * 308 | dat[["sei"]], abs(1.5), 309 | dat[["sei"]]) # Calculate power for each study for an effect of 1.5 310 | dat[["power_es175"]] <- 311 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 312 | abs(1.75), dat[["sei"]])) + 313 | stats::pnorm(stats::qnorm(0.05 / 2) * 314 | dat[["sei"]], abs(1.75), 315 | dat[["sei"]]) # Calculate power for each study for an effect of 1.75 316 | dat[["power_es2"]] <- 317 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 318 | abs(2), dat[["sei"]])) + 319 | stats::pnorm(stats::qnorm(0.05 / 2) * 320 | dat[["sei"]], abs(2), 321 | dat[["sei"]]) # Calculate power for each study for an effect of 2 322 | dat[["power_es225"]] <- 323 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 324 | abs(2.25), dat[["sei"]])) + 325 | stats::pnorm(stats::qnorm(0.05 / 2) * 326 | dat[["sei"]], abs(2.25), 327 | dat[["sei"]]) # Calculate power for each study for an effect of 2.25 328 | dat[["power_es25"]] <- 329 | (1 - stats::pnorm(stats::qnorm(1 - 0.05 / 2) * dat[["sei"]], 330 | abs(2.5), dat[["sei"]])) + 331 | stats::pnorm(stats::qnorm(0.05 / 2) * 332 | dat[["sei"]], abs(2.5), 333 | dat[["sei"]]) # Calculate power for each study for an effect of 2.5 334 | dat <- as.data.frame(dat) 335 | power_median_dat <- data.frame(power_es_observed=numeric(1), 336 | es025=numeric(1), 337 | es05=numeric(1), 338 | es075=numeric(1), 339 | es1=numeric(1), 340 | es125=numeric(1), 341 | es15=numeric(1), 342 | es175=numeric(1), 343 | es2=numeric(1), 344 | es225=numeric(1), 345 | es25=numeric(1) 346 | 347 | ) 348 | power_median_dat[["es_observed"]] <- median(dat[["power_es_observed"]]) 349 | power_median_dat[["es025"]] <- median(dat[["power_es025"]]) 350 | power_median_dat[["es05"]] <- median(dat[["power_es05"]]) 351 | power_median_dat[["es075"]] <- median(dat[["power_es075"]]) 352 | power_median_dat[["es1"]] <- median(dat[["power_es1"]]) 353 | power_median_dat[["es125"]] <- median(dat[["power_es125"]]) 354 | power_median_dat[["es15"]] <- median(dat[["power_es15"]]) 355 | power_median_dat[["es175"]] <- median(dat[["power_es175"]]) 356 | power_median_dat[["es2"]] <- median(dat[["power_es2"]]) 357 | power_median_dat[["es225"]] <- median(dat[["power_es225"]]) 358 | power_median_dat[["es25"]] <- median(dat[["power_es25"]]) 359 | power_median_dat <- as.data.frame(power_median_dat) 360 | power_median_dat <- dplyr::mutate(power_median_dat, 361 | meta_analysis_name = name) 362 | } 363 | 364 | } 365 | } 366 | value <- list( 367 | dat = dat, 368 | power_median_dat = power_median_dat 369 | ) # Create a list of output objects 370 | attr(value, "class") <- "mapower_se_t2" 371 | value 372 | } 373 | -------------------------------------------------------------------------------- /README.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | output: github_document 3 | --- 4 | 5 | ```{r setup, include=FALSE} 6 | knitr::opts_chunk$set(collapse = TRUE, 7 | comment = "#>", 8 | fig.width = 7, 9 | fig.height = 3) 10 | ``` 11 | 12 | 13 | # metameta: A Meta-meta-analysis Package for R 14 | 15 | [![DOI](https://zenodo.org/badge/279281549.svg)](https://zenodo.org/badge/latestdoi/279281549) 16 | [![Travis build status](https://travis-ci.com/dsquintana/metameta.svg?branch=master)](https://travis-ci.com/dsquintana/metameta) 17 | [![Lifecycle: experimental](https://img.shields.io/badge/lifecycle-experimental-orange.svg)](https://www.tidyverse.org/lifecycle/#experimental) 18 | 19 | 20 | ## Description 21 | 22 | The `metameta` package is a collection of functions for 23 | meta-meta-analyses in R, which is useful for re-analyzing published meta-analysis. Functions are 24 | available to calculate the statistical power for each study in a 25 | meta-analysis, based on data that is typically reported in 26 | meta-analyses, and for creating a “Firepower” plot, which visualizes the 27 | median power of a meta-analysis assuming a range of true effect sizes. 28 | 29 | ## Usage 30 | ### Install the package 31 | 32 | ```{r, message=FALSE, warning=FALSE} 33 | devtools::install_github("dsquintana/metameta") 34 | ``` 35 | 36 | 37 | ### Calculate power for studies included in a published meta-analysis. 38 | 39 | The `mapower_se` function can calculate power for a range of "true" effect sizes: The reported summary effect size estimate and a range of effects from 0.1 to 1 (in increments of 0.1). Here, we're only showing the first 6 columns for the purposes of illustration, although the function calculates power for 11 true effect sizes in total. We're also making our calculations based on reported effect sizes and standard errors 40 | 41 | ```{r, message=FALSE, warning=FALSE} 42 | library(metameta) 43 | library(dplyr) 44 | ``` 45 | 46 | ```{r} 47 | power_ooi <- mapower_se(dat = dat_ooi, observed_es = 0.178, name = "ooi et al 2017") 48 | power_ooi_dat <- power_ooi$dat 49 | power_ooi_dat <- power_ooi_dat %>% select(1:6) # Select first 6 columns 50 | power_ooi_dat 51 | 52 | ``` 53 | 54 | We can also perform the same analysis using effect size and confidence interval data, using the `mapower_ul` function. As before, only a small selection of columns are printed for the purposes of demonstration. 55 | 56 | ```{r} 57 | power_keech <- mapower_ul(dat = dat_keech, observed_es = 0.08, name = "Keech et al 2017") 58 | power_keech_dat <- power_keech$dat 59 | power_keech_dat <- power_keech_dat %>% select(1:6) # Select first 6 columns 60 | power_keech_dat 61 | ``` 62 | 63 | ### Create a Firepower plot 64 | 65 | Sometimes it's useful to calculate the statistical power for a body of meta-analyses, which might be reported in the same article or across articles. Illustrating the power of individual studies from multiple meta-analyses can be difficult to interpret if there are many studies. An alternative is to illustrate the power per meta-analysis by calculating the mean power across studies. We can illustrate this with a "Firepower" plot. This plot visualizes the median power assuming the observed effect size in the meta-analysis is the true effect size as well as assuming a range of true effect sizes ranging from 0.1 to 1 (in increments of 0.1). 66 | 67 | ```{r, message=FALSE} 68 | library(metameta) 69 | 70 | ### Calcuate median power for three meta-analyses 71 | power_ooi <- mapower_se(dat = dat_ooi, observed_es = 0.178, name = "ooi et al 2017") 72 | power_med_ooi <- power_ooi$power_median_dat 73 | 74 | keech_power <- mapower_ul(dat = dat_keech, observed_es = 0.08, name = "Keech et al 2017") 75 | power_med_keech <- keech_power$power_median_dat 76 | 77 | power_bakermans_kranenburg <- 78 | mapower_se(dat = dat_bakermans_kranenburg, observed_es = 0.32, 79 | name = "Bakermans-Kranenburg et al 2013") 80 | power_med_bakermans_kranenburg <- power_bakermans_kranenburg$power_median_dat 81 | 82 | ### Create a list 83 | list_power <- list(power_med_ooi, power_med_keech, power_med_bakermans_kranenburg) 84 | 85 | ### Run firepower function 86 | fp <- firepower(list_power) 87 | 88 | ### Create firepower plot 89 | fp_plot <- fp$fp_plot 90 | fp_plot 91 | ``` 92 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # metameta: A Meta-meta-analysis Package for R 3 | 4 | ## Description 5 | 6 | The `metameta` package facilitates the calculation and visualization of study-level statistical power in meta-analyses for a range of hypothetical effect sizes. The package can be used to re-analyze published meta-analyses using information typically presented in meta-analysis forest plots or when reporting novel meta-analyses. 7 | 8 | For a full guide and/or an object to cite, see this manuscript: https://doi.org/10.31219/osf.io/js79t. Full citation details are available below. 9 | 10 | ## Usage 11 | 12 | ### Install the package 13 | 14 | ``` r 15 | devtools::install_github("dsquintana/metameta") 16 | ``` 17 | 18 | ### Calculate power for studies included in a published meta-analysis. 19 | 20 | The `mapower_se` function can calculate power for a range of “true” 21 | effect sizes: The reported summary effect size estimate and a range of 22 | effects from 0.1 to 1 (in increments of 0.1). Here, we’re only showing 23 | the first 6 columns for the purposes of illustration, although the 24 | function calculates power for 11 true effect sizes in total. We’re also 25 | making our calculations based on reported effect sizes and standard 26 | errors 27 | 28 | ``` r 29 | library(metameta) 30 | library(dplyr) 31 | ``` 32 | 33 | ``` r 34 | power_ooi <- mapower_se(dat = dat_ooi, observed_es = 0.178, name = "ooi et al 2017") 35 | power_ooi_dat <- power_ooi$dat 36 | power_ooi_dat <- power_ooi_dat %>% select(1:6) # Select first 6 columns 37 | power_ooi_dat 38 | #> study yi sei power_es_observed power_es01 power_es02 39 | #> 1 anagnostou_2012 1.187 0.479 0.06596450 0.05500761 0.07020009 40 | #> 2 andari_2010 0.155 0.380 0.07549262 0.05797045 0.08229066 41 | #> 3 dadds_2014 -0.230 0.319 0.08636394 0.06133177 0.09610698 42 | #> 4 domes_2013 -0.185 0.368 0.07720550 0.05850133 0.08446626 43 | #> 5 domes_2014 0.824 0.383 0.07508974 0.05784552 0.08177903 44 | #> 6 gordon_2013 -0.182 0.336 0.08272160 0.06020765 0.09147592 45 | #> 7 guastella_2010 0.235 0.346 0.08082964 0.05962295 0.08907113 46 | #> 8 guastella_2015b 0.069 0.279 0.09777789 0.06484272 0.11062850 47 | #> 9 watanabe_2014 0.245 0.222 0.12627341 0.07355100 0.14689796 48 | ``` 49 | 50 | We can also perform the same analysis using effect size and confidence 51 | interval data, using the `mapower_ul` function. As before, only a small 52 | selection of columns are printed for the purposes of 53 | demonstration. 54 | 55 | ``` r 56 | power_keech <- mapower_ul(dat = dat_keech, observed_es = 0.08, name = "Keech et al 2017") 57 | power_keech_dat <- power_keech$dat 58 | power_keech_dat <- power_keech_dat %>% select(1:6) # Select first 6 columns 59 | power_keech_dat 60 | #> study yi lower upper sei power_es_observed 61 | #> 1 anagnostou_2012 0.79 -0.12 1.71 0.4668367 0.05337078 62 | #> 2 brambilla_2016 0.15 -0.22 0.52 0.1887755 0.07081577 63 | #> 3 davis_2013 0.11 -0.68 0.90 0.4030612 0.05452497 64 | #> 4 domes_2013 -0.18 -0.86 0.50 0.3469388 0.05611304 65 | #> 5 einfeld_2014 0.22 -0.06 0.51 0.1454082 0.08533524 66 | #> 6 fischer-shofty_2013 0.07 -0.20 0.35 0.1403061 0.08799827 67 | #> 7 gibson_2014 -0.12 -1.13 0.89 0.5153061 0.05276549 68 | #> 8 gordon_2013 -0.15 -0.51 0.20 0.1811224 0.07263326 69 | #> 9 guastella_2010 0.59 0.07 1.12 0.2678571 0.06028006 70 | #> 10 guastella_2015 0.05 -0.54 0.64 0.3010204 0.05812977 71 | #> 11 jarskog_2017 -0.30 -0.83 0.23 0.2704082 0.06008590 72 | #> 12 woolley_2014 -0.01 -0.29 0.26 0.1403061 0.08799827 73 | ``` 74 | 75 | ### Create a Firepower plot 76 | 77 | Sometimes it’s useful to calculate the statistical power for a body of 78 | meta-analyses, which might be reported in the same article or across 79 | articles. Illustrating the power of individual studies from multiple 80 | meta-analyses can be difficult to interpret if there are many studies. 81 | An alternative is to illustrate the power per meta-analysis by 82 | calculating the mean power across studies. We can illustrate this with a 83 | “Firepower” plot. This plot visualizes the median power assuming the 84 | observed effect size in the meta-analysis is the true effect size as 85 | well as assuming a range of true effect sizes ranging from 0.1 to 1 (in 86 | increments of 0.1). 87 | 88 | ``` r 89 | library(metameta) 90 | 91 | ### Calcuate median power for three meta-analyses 92 | power_ooi <- mapower_se(dat = dat_ooi, observed_es = 0.178, name = "ooi et al 2017") 93 | power_med_ooi <- power_ooi$power_median_dat 94 | 95 | keech_power <- mapower_ul(dat = dat_keech, observed_es = 0.08, name = "Keech et al 2017") 96 | power_med_keech <- keech_power$power_median_dat 97 | 98 | power_bakermans_kranenburg <- 99 | mapower_se(dat = dat_bakermans_kranenburg, observed_es = 0.32, 100 | name = "Bakermans-Kranenburg et al 2013") 101 | power_med_bakermans_kranenburg <- power_bakermans_kranenburg$power_median_dat 102 | 103 | ### Create a list 104 | list_power <- list(power_med_ooi, power_med_keech, power_med_bakermans_kranenburg) 105 | 106 | ### Run firepower function 107 | fp <- firepower(list_power) 108 | 109 | ### Create firepower plot 110 | fp_plot <- fp$fp_plot 111 | fp_plot 112 | ``` 113 | ![](README_files/figure-gfm/unnamed-chunk-5-1.png) 114 | 115 | ### Citing the metameta package 116 | 117 | I have put in considerable time and effort creating this package. I would really appreciate it if you could cite it when using it for your analyses. 118 | 119 | Quintana, D.S. (2022). A guide for calculating study-level statistical power for meta-analyses. *OSF Preprints*. https://doi.org/10.31219/osf.io/js79t. 120 | 121 | 122 | -------------------------------------------------------------------------------- /README_files/figure-gfm/unnamed-chunk-2-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsquintana/metameta/3d4d701b2c69d97f38c545a4c0c6e2e827d4da08/README_files/figure-gfm/unnamed-chunk-2-1.png -------------------------------------------------------------------------------- /README_files/figure-gfm/unnamed-chunk-3-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsquintana/metameta/3d4d701b2c69d97f38c545a4c0c6e2e827d4da08/README_files/figure-gfm/unnamed-chunk-3-1.png -------------------------------------------------------------------------------- /README_files/figure-gfm/unnamed-chunk-4-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsquintana/metameta/3d4d701b2c69d97f38c545a4c0c6e2e827d4da08/README_files/figure-gfm/unnamed-chunk-4-1.png -------------------------------------------------------------------------------- /README_files/figure-gfm/unnamed-chunk-5-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsquintana/metameta/3d4d701b2c69d97f38c545a4c0c6e2e827d4da08/README_files/figure-gfm/unnamed-chunk-5-1.png -------------------------------------------------------------------------------- /_pkgdown.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsquintana/metameta/3d4d701b2c69d97f38c545a4c0c6e2e827d4da08/_pkgdown.yml -------------------------------------------------------------------------------- /data/dat_bakermans_kranenburg.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsquintana/metameta/3d4d701b2c69d97f38c545a4c0c6e2e827d4da08/data/dat_bakermans_kranenburg.rda -------------------------------------------------------------------------------- /data/dat_keech.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsquintana/metameta/3d4d701b2c69d97f38c545a4c0c6e2e827d4da08/data/dat_keech.rda -------------------------------------------------------------------------------- /data/dat_ooi.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsquintana/metameta/3d4d701b2c69d97f38c545a4c0c6e2e827d4da08/data/dat_ooi.rda -------------------------------------------------------------------------------- /inst/CITATION: -------------------------------------------------------------------------------- 1 | citHeader("To cite metameta in publications use:" ) 2 | 3 | citEntry( 4 | entry = "Article", 5 | title = "A guide for calculating study-level statistical power for meta-analyses", 6 | author = personList(as.person("Daniel S. Quintana")), 7 | journal = "OSF Preprints", 8 | year = "2022", 9 | url = "https://doi.org/10.31219/osf.io/js79t", 10 | textVersion = 11 | paste("Quintana, D.S. (2022).", 12 | "A guide for calculating study-level statistical power for meta-analyses.", 13 | "OSF Preprints.", 14 | "https://doi.org/10.31219/osf.io/js79t") 15 | ) 16 | -------------------------------------------------------------------------------- /man/ci_to_se.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ci_to_se.R 3 | \name{ci_to_se} 4 | \alias{ci_to_se} 5 | \title{Calculate standard error based on confidence intervals} 6 | \usage{ 7 | ci_to_se(lower, upper) 8 | } 9 | \arguments{ 10 | \item{lower}{A lower confidence interval bound} 11 | 12 | \item{upper}{An upper confidence interval bound} 13 | } 14 | \value{ 15 | A standard error value 16 | } 17 | \description{ 18 | Calculate standard error based on confidence intervals 19 | } 20 | \examples{ 21 | ci_to_se(-0.12, 1.71) 22 | ci_to_se(0.07, 1.12) 23 | } 24 | -------------------------------------------------------------------------------- /man/dat_bakermans_kranenburg.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/dat_bakermans_kranenburg.R 3 | \docType{data} 4 | \name{dat_bakermans_kranenburg} 5 | \alias{dat_bakermans_kranenburg} 6 | \title{Studies on the impact of intranasal oxytocin in clinical groups} 7 | \format{ 8 | A data frame with 19 rows and 5 columns: 9 | \describe{ 10 | \item{study}{The name of the first author of the study and the year it was published} 11 | \item{yi}{Effect size measure (Cohen's d)} 12 | \item{sei}{The standard error} 13 | ... 14 | } 15 | } 16 | \usage{ 17 | dat_bakermans_kranenburg 18 | } 19 | \description{ 20 | This is data from a meta-analysis on 19 studies investigating the impact of intranasal oxytocin 21 | administration on various clinical-related outcomes in clinical groups. Postive effect size values 22 | are indicative of a positive effect of intranasal oxytocin on outcomes. Effect size 23 | measure confidence intervals, and standard errors were extracted from Figure 2 of the 24 | article (see reference below). 25 | } 26 | \examples{ 27 | power_bakermans_kranenburg <- 28 | mapower_se( 29 | dat = dat_bakermans_kranenburg, 30 | observed_es = 0.32, 31 | name = "Bakermans-Kranenburg et al 2013" 32 | ) 33 | 34 | } 35 | \references{ 36 | { 37 | Bakermans-Kranenburg MJ, van I Jzendoorn MH. Sniffing around oxytocin: review and 38 | meta-analyses of trials in healthy and clinical groups with implications for 39 | pharmacotherapy. 40 | \emph{Translational Psychiatry}, \bold{3}, e258. 41 | } 42 | } 43 | \keyword{datasets} 44 | -------------------------------------------------------------------------------- /man/dat_keech.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/dat_keech.R 3 | \docType{data} 4 | \name{dat_keech} 5 | \alias{dat_keech} 6 | \title{Studies on the impact of intranasal oxytocin on emotion recognition in neurodevelopmental disorders} 7 | \format{ 8 | A data frame with 13 rows and 3 columns: 9 | \describe{ 10 | \item{study}{The name of the first author of the study and the year it was published} 11 | \item{yi}{Effect size measure (Hedges' g)} 12 | \item{lower}{The lower bound of a 95\% confidence interval} 13 | \item{upper}{The upper bound of a 95\% confidence interval} 14 | ... 15 | } 16 | } 17 | \usage{ 18 | dat_keech 19 | } 20 | \description{ 21 | This is data from a meta-analysis on 12 studies investigating the impact of intranasal oxytocin 22 | administration on emotion recognition in neurodevelopmental disorders. Postive effect size values 23 | are indicative of a positive effect of intranasal oxytocin on emotion recognition. Effect size 24 | measure and confidence intervals were extracted from Figure 2 of the article (see reference below). 25 | } 26 | \examples{ 27 | power_keech <- 28 | mapower_ul( 29 | dat = dat_keech, 30 | observed_es = 0.08, 31 | name = "Keech et al 2018" 32 | ) 33 | } 34 | \references{ 35 | { 36 | Keech, B., Crowe, S., & Hocking, D. R. (2018). Intranasal oxytocin, 37 | social cognition and neurodevelopmental disorders: a meta-analysis 38 | \emph{Psychoneuroendocrinology}, \bold{87}, 9--19. 39 | } 40 | } 41 | \keyword{datasets} 42 | -------------------------------------------------------------------------------- /man/dat_ooi.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/dat_ooi.R 3 | \docType{data} 4 | \name{dat_ooi} 5 | \alias{dat_ooi} 6 | \title{Studies on the impact of intranasal oxytocin on social cognition in autism spectrum disorders} 7 | \format{ 8 | A data frame with 9 rows and 3 columns: 9 | \describe{ 10 | \item{study}{The name of the first author of the study and the year it was published} 11 | \item{yi}{Effect size measure (Hedges' g)} 12 | \item{sei}{The standard error} 13 | ... 14 | } 15 | } 16 | \usage{ 17 | dat_ooi 18 | } 19 | \description{ 20 | This is data from a meta-analysis on 9 studies investigating the impact of intranasal oxytocin 21 | administration on social cognition in autism spectrum disorders. Postive effect size values 22 | are indicative of a positive effect of intranasal oxytocin on social cognition. Effect size 23 | measure and confidence intervals were extracted from Figure 2 of the article (see reference below). 24 | } 25 | \examples{ 26 | power_ooi <- 27 | mapower_se( 28 | dat = dat_ooi, 29 | observed_es = 0.178, 30 | name = "Ooi et al 2017" 31 | ) 32 | } 33 | \references{ 34 | { 35 | Ooi YP, Weng SJ, Kossowsky J, Gerger H, Sung M. (2017). Oxytocin and Autism Spectrum Disorders: 36 | A Systematic Review and Meta-Analysis of Randomized Controlled Trials. 37 | \emph{Pharmacopsychiatry}, \bold{50}, 5--13. 38 | } 39 | } 40 | \keyword{datasets} 41 | -------------------------------------------------------------------------------- /man/firepower.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/firepower.R 3 | \name{firepower} 4 | \alias{firepower} 5 | \title{Calculate the median study power for a meta-analysis and visualise this data using a Firepower plot} 6 | \usage{ 7 | firepower(power_list, size = "medium", es = "Effect size") 8 | } 9 | \arguments{ 10 | \item{power_list}{A list of dataframes with calculated power, derived from the "mapower_ul" or "mapower_se" 11 | functions. See 'Examples' for how to make a list.} 12 | 13 | \item{size}{The effect size range, as specified using the mapower_se() or mapower_ul() functions, 14 | which created the 'power_list' dataframe or dataframes. 15 | The default is a medium range is 0.1 to 1, in increments of 0.1. 16 | Other options include a "small" range (0.05 to 0.5 in increments of 0.05) and a "large" 17 | range (0.25 to 2.5 in increments of 0.25).} 18 | 19 | \item{es}{An optional string for the name of the effect size for the plot (e.g., "Hedges g"). 20 | The default string is "Effect size".} 21 | } 22 | \value{ 23 | This function returns the following: 24 | \item{dat}{A dataset with the median results from power analyses for a range of effect sizes, including the 25 | specified true effect size, in a column labelled "power_true". The additional added columns include 26 | results for power analysis assuming a range of true effect sizes, with the default beginning at 0.1 ("power_es01"), 27 | then 0.2 ("power_es02"), then continuing in increments of 0.1 up to 1 ("power_es1"). A 28 | "small" and "large" effect size range is also possible (see the 'size' argument 29 | for details)} 30 | \item{fp_plot}{A firepower plot} 31 | } 32 | \description{ 33 | Creates a dataset with median power and a firepower plot, which visualises the median power for a 34 | meta-analysis assuming the observed effect size in the meta-analysis is the true effect size and assuming a 35 | range of true effect sizes ranging from 0.1 to 1 in increments of 0.1. See 'Details'. 36 | } 37 | \details{ 38 | \strong{The true effect size} 39 | 40 | For the purposes of power analysis a "true" effect size needs to be specified. However, 41 | the true effect size is unknown when testing hypotheses and reported summary 42 | effect sizes are typically inflated. Thus, Firepower plots implements two alternative 43 | categories for a true effect for the purposes of power 44 | analysis: The observed summary effect size estimate reported in the meta-analysis and statistical power for 45 | a range of true effect sizes, The default "medium" range is from 0.1 to 1, in increments of 0.1. 46 | However, a "small" and "large" range is also available (see the "size" argument below for details). 47 | } 48 | \examples{ 49 | ### Calcuate median power for meta-analyses 50 | power_ooi <- mapower_se(dat = dat_ooi, observed_es = 0.178, name = "ooi et al 2017") 51 | power_med_ooi <- power_ooi$power_median_dat 52 | 53 | keech_power <- mapower_ul(dat = dat_keech, observed_es = 0.08, name = "Keech et al 2017") 54 | power_med_keech <- keech_power$power_median_dat 55 | 56 | power_bakermans_kranenburg <- mapower_se(dat = dat_bakermans_kranenburg, observed_es = 0.32, name = "Bakermans-Kranenburg et al 2013") 57 | power_med_bakermans_kranenburg <- power_bakermans_kranenburg$power_median_dat 58 | 59 | ### Create a list 60 | list_power <- list(power_med_ooi, power_med_keech, power_med_bakermans_kranenburg) 61 | 62 | ### Run firepower function 63 | fp <- firepower(list_power) 64 | 65 | ### Extract data from datasets in list 66 | power_dat <- fp$dat 67 | power_dat 68 | 69 | ### Create firepower plot 70 | fp_plot <- fp$fp_plot 71 | fp_plot 72 | 73 | } 74 | -------------------------------------------------------------------------------- /man/mapower_se.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mapower_se.R 3 | \name{mapower_se} 4 | \alias{mapower_se} 5 | \title{Calculate statistical power using effect size and standard error data} 6 | \usage{ 7 | mapower_se(dat, size = "medium", observed_es, name) 8 | } 9 | \arguments{ 10 | \item{dat}{A dataset that contains one column with observed effect sizes or outcomes 11 | labelled "yi" and a column with standard error data, labelled "sei".} 12 | 13 | \item{size}{The effect size range. The default is a medium range (0.1 to 1, in increments of 0.1). 14 | In other words, if you do not use this argument, the medium range will be used. 15 | Other options include a "small" range (0.05 to 0.5 in increments of 0.05) and a "large" 16 | range (0.25 to 2.5 in increments of 0.25).} 17 | 18 | \item{observed_es}{The observed summary effect size estimate for the meta-analysis, which is one output 19 | for the set of possible "true" effect sizes. See 'Details'} 20 | 21 | \item{name}{A label with a name for the meta-analysis, which is required for using the "firepower" function. 22 | See 'Examples'} 23 | } 24 | \value{ 25 | This function returns the following: 26 | \item{dat}{A dataset with results from power analyses for a range of effect sizes, including the 27 | specified observed effect size, in a column labelled "es_observed". The additional added columns include 28 | results for power analysis assuming a range of true effect sizes, with the default beginning at 0.1 ("power_es01"), 29 | then 0.2 ("power_es02"), then continuing in increments of 0.1 up to 1 ("power_es1"). A smaller 30 | or larger range of effect sizes can be specified (see the 'size' argument for details)} 31 | } 32 | \description{ 33 | Calculate statistical power using effect size and standard error data that 34 | is typically reported in meta-analyses. Power is calculated assuming 35 | the summary effect size in a meta-analysis is true effect size and assuming a 36 | range of effect sizes. The script to calculate power 37 | was adapted from the "viz_sunset" function of the metaviz package. 38 | } 39 | \details{ 40 | \strong{The true effect size} 41 | 42 | For the purposes of power analysis a "true" effect size needs to be specified. However, 43 | the true effect size is unknown when testing hypotheses and reported summary 44 | effect sizes are typically inflated. Here, the observed summary effect size estimate 45 | reported in the meta-analysis results is used as one possible true effect size, however, 46 | other effect sizes can be specified here instead. Additionally, statistical power for a range 47 | of true effect sizes are returned. The default is a "medium" range from 0.1 to 1, 48 | in increments of 0.1. However, a "small" and "large" range is also available 49 | (see the "size" argument below for details). 50 | } 51 | \examples{ 52 | ### An analysis using the default effect size range 53 | 54 | power_ooi <- mapower_se( 55 | dat = dat_ooi, 56 | observed_es = 0.178, 57 | name = "ooi et al 2017") 58 | power_ooi 59 | 60 | ### An analysis using the large effect size range 61 | 62 | power_ooi_l <- mapower_se( 63 | dat = dat_ooi, 64 | size = "large", 65 | observed_es = 0.178, 66 | name = "ooi et al 2017") 67 | power_ooi_l 68 | 69 | ### An analysis using the small effect size range 70 | 71 | power_ooi_s <- mapower_se( 72 | dat = dat_ooi, 73 | size = "small", 74 | observed_es = 0.178, 75 | name = "ooi et al 2017") 76 | power_ooi_s 77 | 78 | } 79 | -------------------------------------------------------------------------------- /man/mapower_ul.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mapower_ul.R 3 | \name{mapower_ul} 4 | \alias{mapower_ul} 5 | \title{Calculate statistical power using effect size and confidence interval data} 6 | \usage{ 7 | mapower_ul(dat, size = "medium", observed_es, name) 8 | } 9 | \arguments{ 10 | \item{dat}{A dataset that contains one column with observed effect sizes or outcomes 11 | labelled "yi", a column labelled "lower" with the lower confidence 12 | interval bound, and column labelled "upper" with the upper confidence 13 | interval bound. This function assumes a 95\% confidence interval.} 14 | 15 | \item{size}{The effect size range. The default is a medium range (0.1 to 1, in increments of 0.1). 16 | In other words, if you do not use this argument, the medium range will be used. 17 | Other options include a "small" range (0.05 to 0.5 in increments of 0.05) and a "large" 18 | range (0.25 to 2.5 in increments of 0.25).} 19 | 20 | \item{observed_es}{The observed summary effect size estimate for the meta-analysis, which is one output 21 | for the set of possible "true" effect sizes. See 'Details'} 22 | 23 | \item{name}{A label with a name for the meta-analysis, which is required for using the "firepower" function. 24 | See 'Examples'} 25 | } 26 | \value{ 27 | This function returns the following: 28 | \item{dat}{A dataset with results from power analyses for a range of effect sizes, including the 29 | specified observed effect size, in a column labelled "es_observed". The additional added columns include 30 | results for power analysis assuming a range of true effect sizes, with the default beginning at 0.1 ("power_es01"), 31 | then 0.2 ("power_es02"), then continuing in increments of 0.1 up to 1 ("power_es1"). A smaller 32 | or larger range of effect sizes can be specified (see the 'size' argument for details)} 33 | } 34 | \description{ 35 | Calculate statistical power using effect size and confidence interval data that 36 | is typically reported in meta-analyses. Power is calculated assuming 37 | the true effect size and a range of effect sizes. The script to calculate power 38 | was adapted from the "viz_sunset" function of the metaviz package. 39 | } 40 | \details{ 41 | \strong{The true effect size} 42 | 43 | For the purposes of power analysis a "true" effect size needs to be specified. However, 44 | the true effect size is unknown when testing hypotheses and reported summary 45 | effect sizes are typically inflated. Here, the observed summary effect size estimate 46 | reported in the meta-analysis results is used as one possible true effect size, however, 47 | other effect sizes can be specified here instead. Additionally, statistical power for a range 48 | of true effect sizes are returned. The default is a "medium" range from 0.1 to 1, 49 | in increments of 0.1. However, a "small" and "large" range is also available 50 | (see the "size" argument below for details). 51 | } 52 | \examples{ 53 | 54 | ### An analysis using the default effect size range 55 | 56 | keech_power <- mapower_ul( 57 | dat = dat_keech, 58 | observed_es = 0.08, 59 | name = "Keech et al 2017") 60 | keech_power 61 | 62 | ### An analysis using the large effect size range 63 | 64 | keech_power_l <- mapower_ul( 65 | dat = dat_keech, 66 | size = "large", 67 | observed_es = 0.08, 68 | name = "Keech et al 2017") 69 | keech_power_l 70 | 71 | ### An analysis using the small effect size range 72 | 73 | keech_power_s <- mapower_ul( 74 | dat = dat_keech, 75 | size = "small", 76 | observed_es = 0.08, 77 | name = "Keech et al 2017") 78 | keech_power_s 79 | 80 | } 81 | -------------------------------------------------------------------------------- /metameta.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: Sweave 13 | LaTeX: pdfLaTeX 14 | 15 | BuildType: Package 16 | PackageUseDevtools: Yes 17 | PackageInstallArgs: --no-multiarch --with-keep.source 18 | -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | library(testthat) 2 | library(metameta) 3 | 4 | test_check("metameta") 5 | -------------------------------------------------------------------------------- /tests/testthat/test_misc_firepower.R: -------------------------------------------------------------------------------- 1 | #' Calculate the median study power for a meta-analysis and visualise this data using a Firepower plot 2 | #' 3 | #' Creates a dataset with median power and a firepower plot, which visualises the median power for the 4 | #' assuming the observed effect size in the meta-analysis is the true effect size and assuming a 5 | #' range of true effect sizes ranging from 0.1 to 1 in increments of 0.1. See 'Details'. 6 | #' 7 | #' \strong{The true effect size} 8 | #' 9 | #' It is usually difficult to establish a "true" effect size in practice, as reported effect sizes are typically 10 | #' inflated. Firepower plots implements two alternative categories for a true effect for the purposes of power 11 | #' analysis: The observed summary effect size estimate reported in the meta-analysisand statistical power for 12 | #' a range of true effect sizes (0.1 to 1, in increments of 0.1). 13 | #' 14 | #' @param power_list A list of dataframes with calculated power, derived from the "mapower_ul" or "mapower_se" 15 | #' functions. See 'Examples' for how to make a list. 16 | #' @return This function returns the following: 17 | #' \item{dat}{A dataset with the median results from power analyses for a range of effect sizes, including the 18 | #' specified true effect size, in a column labelled "power_true". The additional added columns include 19 | #' results for power analysis assuming a range of true effect sizes, beginning at 0.1 ("power_es01"), 20 | #' then 0.2 ("power_es02"), then continuing in increments of 0.1 up to 1 ("power_es1").} 21 | #' \item{fp_plot}{A firepower plot} 22 | #' @examples 23 | #' ### Calcuate median power for meta-analyses 24 | #' power_ooi <- mapower_se(dat = dat_ooi, observed_es = 0.178, name = "ooi et al 2017") 25 | #' power_med_ooi <- power_ooi$power_median_dat 26 | #' 27 | #' keech_power <- mapower_ul(dat = dat_keech, observed_es = 0.08, name = "Keech et al 2017") 28 | #' power_med_keech <- keech_power$power_median_dat 29 | #' 30 | #' power_bakermans_kranenburg <- mapower_se(dat = dat_bakermans_kranenburg, observed_es = 0.32, name = "Bakermans-Kranenburg et al 2013") 31 | #' power_med_bakermans_kranenburg <- power_bakermans_kranenburg$power_median_dat 32 | #' 33 | #' ### Create a list 34 | #' list_power <- list(power_med_ooi, power_med_keech, power_med_bakermans_kranenburg) 35 | #' 36 | #' ### Run firepower function 37 | #' fp <- firepower(list_power) 38 | #' 39 | #' ### Extract data from datasets in list 40 | #' power_dat <- fp$dat 41 | #' power_dat 42 | #' 43 | #' ### Create firepower plot 44 | #' fp_plot <- fp$fp_plot 45 | #' fp_plot 46 | 47 | firepower <- function(power_list){ 48 | #'@import ggplot2 49 | #'@import tidyr 50 | #'@import ggthemes 51 | 52 | firepower_list <- lapply(power_list, function(x) x[, 53 | c("es_observed", 54 | "es01", "es02", 55 | "es03", "es04", 56 | "es05", "es06", 57 | "es07", "es08", 58 | "es09", "es1", 59 | "meta_analysis_name" 60 | )]) 61 | 62 | firepower_dat_wide <- do.call(rbind.data.frame, firepower_list) 63 | firepower_dat_wide 64 | power_med_dat_long <- tidyr::gather(firepower_dat_wide, 65 | effect, power, es_observed:es1, 66 | factor_key=TRUE) 67 | power_med_dat_long$es_cat <- 68 | ifelse(power_med_dat_long$effect == "es_observed", 69 | c("observed_es"), 70 | c("range_es")) 71 | power_med_dat_long 72 | firepower_plot <- ggplot2::ggplot(data = power_med_dat_long) + 73 | ggplot2::geom_tile(ggplot2::aes( 74 | x = effect, 75 | y = meta_analysis_name, 76 | fill = power 77 | )) + 78 | ggplot2::theme(aspect.ratio = 0.3) + 79 | ggplot2::scale_fill_gradient2( 80 | name = "Power", 81 | midpoint = 0.5, 82 | low = "white", 83 | mid = "orange", 84 | high = "red" 85 | ) + 86 | ggplot2::facet_grid( ~ es_cat, scale = 'free_x', space = "free_x") + 87 | ggthemes::theme_tufte(base_family = "Helvetica") 88 | 89 | firepower_plot <- 90 | firepower_plot + ggplot2::theme(strip.text.x = ggplot2::element_blank()) 91 | firepower_plot <- firepower_plot + ggplot2::labs(x ="Effect size", y = "") 92 | firepower_plot <- 93 | firepower_plot + ggplot2::scale_x_discrete( 94 | labels = c( 95 | "es_observed" = "Observed", 96 | "es01" = "0.1", 97 | "es02" = "0.2", 98 | "es03" = "0.3", 99 | "es04" = "0.4", 100 | "es05" = "0.5", 101 | "es06" = "0.6", 102 | "es07" = "0.7", 103 | "es08" = "0.8", 104 | "es09" = "0.9", 105 | "es1" = "1" 106 | )) 107 | plot <- firepower_plot 108 | plot 109 | value <- list( 110 | fp_plot = plot, 111 | dat = firepower_dat_wide 112 | ) # Create a list of output objects 113 | attr(value, "class") <- "firepower" 114 | value 115 | } 116 | -------------------------------------------------------------------------------- /vignettes/.gitignore: -------------------------------------------------------------------------------- 1 | *.R 2 | -------------------------------------------------------------------------------- /vignettes/introduction.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Using the metameta package" 3 | output: rmarkdown::html_vignette 4 | vignette: > 5 | %\VignetteIndexEntry{Using the metameta package} 6 | %\VignetteEngine{knitr::rmarkdown} 7 | %\VignetteEncoding{UTF-8} 8 | --- 9 | 10 | ```{r, include = FALSE} 11 | knitr::opts_chunk$set( 12 | collapse = TRUE, 13 | comment = "#>", 14 | fig.width = 7, 15 | fig.height = 3 16 | ) 17 | ``` 18 | 19 | 20 | 21 | The metameta package includes a set of functions to re-analyse published meta-analyses. Let's begin by calculating the statistical power of each study included in a meta-analysis. This function will calulate power assuming that the reported summary effect size estimate is the true effect sizes (the "observed_es" argument) as well as assuming a range of possible true effect sizes, ranging from 0.1 to 1 (in increments of 0.1). 22 | 23 | This particular meta-analysis includes 9 studies, and reported both the effect size and standard error in a forest plot (for more information on this study, see the documentation page: `?dat_ooi`). Here, we're only showing the first 6 columns for the purposes of illustration, although the function calculates power for 11 true effect sizes in total. 24 | 25 | ```{r, message=FALSE} 26 | library(metameta) 27 | library(dplyr) 28 | 29 | power_ooi <- mapower_se(dat = dat_ooi, observed_es = 0.178, name = "ooi et al 2017") 30 | power_ooi_dat <- power_ooi$dat 31 | power_ooi_dat <- power_ooi_dat %>% select(1:6) # Select first 6 columns 32 | power_ooi_dat 33 | ``` 34 | 35 | There's also a similar function for calculating the statisical power of a meta-analysis that reports effect size and _confidence interval data_, which is often reported if standard error data isn't reported. As before, we're only printing a selection of columns. 36 | 37 | ```{r, message=FALSE} 38 | library(metameta) 39 | library(dplyr) 40 | 41 | power_keech <- mapower_ul(dat = dat_keech, observed_es = 0.08, name = "Keech et al 2017") 42 | power_keech_dat <- power_keech$dat 43 | power_keech_dat <- power_keech_dat %>% select(1:6) # Select first 6 columns 44 | power_keech_dat 45 | ``` 46 | 47 | Sometimes it's useful to calculate the statistical power for a body of meta-analyses, which might be reported in the same article or accross articles. Illustrating the power of individual studies from multiple meta-analyses can be difficult to interpret if there are many studies. An alternative is to illustrate the power per meta-analysis by calculating the mean power accross studies. We can illustrate this with a "Firepower" plot. 48 | 49 | Before we create our Firepower plot, we need to prepare the datafile 50 | 51 | ```{r, message=FALSE} 52 | ### Calcuate median power for three meta-analyses 53 | power_ooi <- mapower_se(dat = dat_ooi, observed_es = 0.178, name = "ooi et al 2017") 54 | power_med_ooi <- power_ooi$power_median_dat 55 | 56 | keech_power <- mapower_ul(dat = dat_keech, observed_es = 0.08, name = "Keech et al 2017") 57 | power_med_keech <- keech_power$power_median_dat 58 | 59 | power_bakermans_kranenburg <- 60 | mapower_se(dat = dat_bakermans_kranenburg, observed_es = 0.32, 61 | name = "Bakermans-Kranenburg et al 2013") 62 | power_med_bakermans_kranenburg <- power_bakermans_kranenburg$power_median_dat 63 | 64 | ### Create a list 65 | list_power <- list(power_med_ooi, power_med_keech, power_med_bakermans_kranenburg) 66 | ``` 67 | 68 | Now, we can create our plot using the list we created. 69 | 70 | ```{r, message=FALSE} 71 | ### Run firepower function 72 | fp <- firepower(list_power) 73 | 74 | ### Create firepower plot 75 | fp_plot <- fp$fp_plot 76 | fp_plot 77 | ``` 78 | 79 | You can also print and store the data underlying this figure. 80 | 81 | ```{r, message=FALSE} 82 | fp_data <- fp$dat 83 | fp_data 84 | ``` 85 | --------------------------------------------------------------------------------