tidyBF package is a tidy wrapper around the BayesFactor package that always expects the data to be in the tidy format and return a tibble containing Bayes Factor values. Additionally, it provides a more consistent syntax and by default returns a dataframe with rich details. These functions can also return expressions containing results from Bayes Factor tests that can then be displayed in custom plots.
To get the latest, stable CRAN release:
install.packages("tidyBF")
You can get the development version of the package from GitHub. To see what new changes (and bug fixes) have been made to the package since the last release on CRAN, you can check the detailed log of changes here: https://indrajeetpatil.github.io/tidyBF/news/index.html
If you are in hurry and want to reduce the time of installation, prefer-
# needed package to download from GitHub repo install.packages("remotes") remotes::install_github( repo = "IndrajeetPatil/tidyBF", # package path on GitHub quick = TRUE # skips docs, demos, and vignettes )
If time is not a constraint-
remotes::install_github( repo = "IndrajeetPatil/tidyBF", # package path on GitHub dependencies = TRUE, # installs packages which `tidyBF` depends on upgrade_dependencies = TRUE # updates any out of date dependencies )
Below are few concrete examples of where tidyBF wrapper might provide a more friendly way to access output from or write functions around BayesFactor.
BayesFactor is inconsistent with its formula interface. tidyBF avoids this as it doesn’t provide the formula interface for any of the functions.
# setup set.seed(123) # with `BayesFactor` ---------------------------------------- suppressPackageStartupMessages(library(BayesFactor)) data(sleep) # independent t-test: accepts formula interface ttestBF(formula = wt ~ am, data = mtcars) #> Bayes factor analysis #> -------------- #> [1] Alt., r=0.707 : 1383.367 ±0% #> #> Against denominator: #> Null, mu1-mu2 = 0 #> --- #> Bayes factor type: BFindepSample, JZS # paired t-test: doesn't accept formula interface ttestBF(formula = extra ~ group, data = sleep, paired = TRUE) #> Error in ttestBF(formula = extra ~ group, data = sleep, paired = TRUE): Cannot use 'paired' with formula. # with `tidyBF` ---------------------------------------- library(tidyBF) # independent t-test bf_ttest(data = mtcars, x = am, y = wt) #> # A tibble: 1 x 13 #> term estimate conf.low conf.high pd rope.percentage #> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> #> 1 Difference -1.26 -1.70 -0.820 1 0 #> prior.distribution prior.location prior.scale effect component bf10 #> <chr> <dbl> <dbl> <chr> <chr> <dbl> #> 1 cauchy 0 0.707 fixed conditional 1383. #> log_e_bf10 #> <dbl> #> 1 7.23 # paired t-test bf_ttest(data = sleep, x = group, y = extra, paired = TRUE) #> # A tibble: 1 x 13 #> term estimate conf.low conf.high pd rope.percentage #> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> #> 1 Difference 1.40 0.697 2.10 0.996 0 #> prior.distribution prior.location prior.scale effect component bf10 #> <chr> <dbl> <dbl> <chr> <chr> <dbl> #> 1 cauchy 0 0.707 fixed conditional 17.3 #> log_e_bf10 #> <dbl> #> 1 2.85
Although all functions default to returning a dataframe, you can also use it to extract expressions that can be displayed in plots.
# setup set.seed(123) library(ggplot2) # using the expression to display details in a plot ggplot(ToothGrowth, aes(supp, len)) + geom_boxplot() + # two-sample t-test results in an expression labs(subtitle = bf_ttest(ToothGrowth, supp, len, output = "alternative"))

# setup set.seed(123) library(ggplot2) library(ggforce) library(tidyBF) # plot with subtitle ggplot(iris, aes(x = Species, y = Sepal.Length)) + geom_violin() + geom_sina() + labs(subtitle = bf_oneway_anova(iris, Species, Sepal.Length, output = "h0"))

# setup set.seed(123) library(ggplot2) library(tidyBF) # using the expression to display details in a plot ggplot(mtcars, aes(wt, mpg)) + # Pearson's r results in an expression geom_point() + geom_smooth(method = "lm") + labs(subtitle = bf_corr_test(mtcars, wt, mpg, output = "null")) #> `geom_smooth()` using formula 'y ~ x'

# setup set.seed(123) library(ggplot2) library(tidyBF) # basic pie chart ggplot(as.data.frame(table(mpg$class)), aes(x = "", y = Freq, fill = factor(Var1))) + geom_bar(width = 1, stat = "identity") + theme(axis.line = element_blank()) + # cleaning up the chart and adding results from one-sample proportion test coord_polar(theta = "y", start = 0) + labs( fill = "Class", x = NULL, y = NULL, title = "Pie Chart of class (type of car)", subtitle = bf_contingency_tab(as.data.frame(table(mpg$class)), Var1, counts = Freq, output = "h1")$expr )

# setup set.seed(123) library(metaviz) library(ggplot2) # meta-analysis forest plot with results random-effects meta-analysis viz_forest( x = mozart[, c("d", "se")], study_labels = mozart[, "study_name"], xlab = "Cohen's d", variant = "thick", type = "cumulative" ) + # use `statsExpressions` to create expression containing results labs( title = "Meta-analysis of Pietschnig, Voracek, and Formann (2010) on the Mozart effect", subtitle = bf_meta(dplyr::rename(mozart, estimate = d, std.error = se), output = "h1")$expr ) + theme(text = element_text(size = 12))

BayesFactor objectsThe package provides bf_extractor function to conveniently extract important details from these objects:
# setup set.seed(123) library(tidyBF) library(BayesFactor) data(puzzles) # model result <- anovaBF( RT ~ shape * color + ID, data = puzzles, whichRandom = "ID", whichModels = "top", progress = FALSE ) # extract details bf_extractor(result) #> # A tibble: 21 x 13 #> term estimate conf.low conf.high pd rope.percentage #> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> #> 1 mu 45.0 43.9 46.1 1 0 #> 2 shape-round 0.429 0.131 0.741 0.992 0.141 #> 3 shape-square -0.429 -0.741 -0.131 0.992 0.141 #> 4 color-color -0.426 -0.711 -0.0995 0.990 0.162 #> 5 color-monochromatic 0.426 0.0995 0.711 0.990 0.162 #> 6 ID-1 2.47 1.04 3.98 0.995 0 #> 7 ID-2 0.439 -1.02 1.78 0.698 0.231 #> 8 ID-3 0.907 -0.501 2.32 0.848 0.156 #> 9 ID-4 0.466 -0.959 1.98 0.704 0.218 #> 10 ID-5 3.17 1.83 4.66 0.999 0 #> prior.distribution prior.location prior.scale effect component bf10 #> <chr> <dbl> <dbl> <chr> <chr> <dbl> #> 1 <NA> NA NA fixed extra 2.65 #> 2 <NA> NA NA fixed conditional 0.233 #> 3 <NA> NA NA fixed conditional 0.239 #> 4 <NA> NA NA fixed conditional 2.65 #> 5 <NA> NA NA fixed conditional 0.233 #> 6 <NA> NA NA random conditional 0.239 #> 7 <NA> NA NA random conditional 2.65 #> 8 <NA> NA NA random conditional 0.233 #> 9 <NA> NA NA random conditional 0.239 #> 10 <NA> NA NA random conditional 2.65 #> log_e_bf10 #> <dbl> #> 1 0.974 #> 2 -1.45 #> 3 -1.43 #> 4 0.974 #> 5 -1.45 #> 6 -1.43 #> 7 0.974 #> 8 -1.45 #> 9 -1.43 #> 10 0.974 #> # ... with 11 more rows
BayesFactor can return the Bayes Factor value corresponding to either evidence in favor of the null hypothesis over the alternative hypothesis (BF01) or in favor of the alternative over the null (BF10), depending on how this object is called. tidyBF on the other hand return both of these values and their logarithms.
# `BayesFactor` object bf <- BayesFactor::correlationBF(y = iris$Sepal.Length, x = iris$Petal.Length) # alternative bf #> Bayes factor analysis #> -------------- #> [1] Alt., r=0.333 : 2.136483e+43 ±0% #> #> Against denominator: #> Null, rho = 0 #> --- #> Bayes factor type: BFcorrelation, Jeffreys-beta* # null 1 / bf #> Bayes factor analysis #> -------------- #> [1] Null, rho = 0 : 4.680589e-44 ±0% #> #> Against denominator: #> Alternative, r = 0.333333333333333, rho =/= 0 #> --- #> Bayes factor type: BFcorrelation, Jeffreys-beta* # `tidyBF` output bf_corr_test(iris, Sepal.Length, Petal.Length, bf.prior = 0.333) #> # A tibble: 1 x 13 #> term estimate conf.low conf.high pd rope.percentage prior.distribution #> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <chr> #> 1 rho 0.863 0.828 0.897 1 0 cauchy #> prior.location prior.scale effect component bf10 log_e_bf10 #> <dbl> <dbl> <chr> <chr> <dbl> <dbl> #> 1 0 0.333 fixed conditional 2.13e43 99.8
Note that the log-transformed values are helpful because in case of strong effects, the raw Bayes Factor values can be pretty large, but the log-transformed values continue to remain easy to work with.
The hexsticker was generously designed by Sarah Otterstetter (Max Planck Institute for Human Development, Berlin).
Please note that the tidyBF project is released with a Contributor Code of Conduct. By contributing to this project, you agree to abide by its terms.