% \VignetteEngine{knitr::knitr}
% \VignetteEncoding{UTF-8}
% \VignetteIndexEntry{Using the bfpwr package}
% \VignetteDepends{knitr}
\documentclass[a4paper, 11pt]{article}
\usepackage[round]{natbib} % references
\usepackage{helvet} % helvetica sans serif font
\usepackage[onehalfspacing]{setspace} % more space
\usepackage[dvipsnames,table]{xcolor} % colors
\usepackage{booktabs} % nicer tables

% margins
\usepackage{geometry}
\geometry{
  a4paper,
  left=20mm,
  right=20mm,
  top=30mm,
  bottom=25mm,
}

% title, author, date, etc.
\title{\textsf{\textbf{Using the bfpwr package}}}
\author{
  \textbf{Samuel Pawel} \\
  \url{https://orcid.org/0000-0003-2779-320X}
}
\date{Package version \Sexpr{packageVersion(pkg = "bfpwr")} \\ \today}

% hyperref options
\usepackage{hyperref}
\hypersetup{
  bookmarksopen=true,
  breaklinks=true,
  pdftitle={Using the bfpwr package},
  pdfsubject={},
  pdfkeywords={},
  colorlinks=true,
  linkcolor=black,
  anchorcolor=black,
  citecolor=blue,
  urlcolor=blue
}

\usepackage{fancyhdr}
\pagestyle{fancy}
\chead{}
\lhead{\textit{Using the \textbf{bfpwr} package}}
\rhead{}

\begin{document}

<< "knitr-options", echo = FALSE >>=
library(knitr)
opts_chunk$set(fig.height = 4.5,
               fig.align = "center",
               cache = FALSE,
               message = FALSE,
               warning = FALSE)
@

\maketitle


\noindent The \textbf{bfpwr} package provides functions to compute commonly used
Bayes factors and perform corresponding power and sample size calculations. The
theoretical background of the package is described in \citet{PawelHeld2025}.
Calculations in \textbf{bfpwr} are performed analytically or with numerical
(non-simulation based) methods. This differs from most other packages that use
simulation methods for the same purposes \citep[e.g., the \textbf{BFDA} package
  from][]{Schoenbrodt2019}. This typically leads to faster computations without
simulation error, but at the cost of being restricted to certain data
distributions and analysis methods. This vignette illustrates how the package
can be used in some typical situations. Table~\ref{tab:mainfunctions} summarizes
the main functions of the package. It is recommended to look at the function
documentation (\texttt{?functionname}) before using them for the first time as
this vignette provides only a broad overview of the package.

\begingroup
\renewcommand{\arraystretch}{1.3} % Default value: 1
\begin{table}[!htb]
  \centering
  \caption{Main functions for Bayes factor analysis and design in the
    \textbf{bfpwr} package.}
  \label{tab:mainfunctions}
  \rowcolors{1}{}{gray!15}
  \begin{tabular}{l l l}
    \toprule
    \textbf{Bayes factor type} & \textbf{Analysis function} & \textbf{Design function} \\
    \midrule
    \textit{z}-test Bayes factor (Section~\ref{sec:ztest}) & \texttt{bf01} & \texttt{powerbf01}\\
    \textit{t}-test Bayes factor (Section~\ref{sec:ttest}) & \texttt{tbf01} & \texttt{powertbf01} \\
    Normal moment Bayes factor (Section~\ref{sec:nonlocal}) & \texttt{nmbf01} & \texttt{powernmbf01} \\
    \bottomrule
  \end{tabular}
\end{table}
\endgroup

\noindent The \textbf{bfpwr} package can be installed from CRAN by running

<< "installation", eval = FALSE >>=
install.packages("bfpwr")
@

% The development version of the package can be installed by running

% << "installation", eval = FALSE >>=
% ## install.packages("remotes")
% remotes::install_github(repo = "SamCH93/bfpwr", subdir = "package")
% @

\noindent followed by loading it with

<< "load" >>=
library("bfpwr")
@

\noindent Development of \textbf{bfpwr} is being done on GitHub. Anyone with
ideas for new features, bug reports, or other contributions to the package is
invited to get in touch there (\url{https://github.com/SamCH93/bfpwr}).

\section{\textit{z}-test Bayes factor}
\label{sec:ztest}
The \textit{z}-test Bayes factor is a fairly general analysis method that is
applicable to data summarized by an estimate $\hat{\theta}$ of an unknown
parameter $\theta$, along with a standard error of the estimate. The estimate is
assumed to be approximately normally distributed around the true parameter with
a standard deviation equal to the standard error. The \textit{z}-test Bayes
factor then quantifies the evidence for the null hypothesis that the parameter
takes a certain null value $H_{0} \colon \theta = \theta_{0}$ against the
alternative hypothesis that it takes another value
$H_{1} \colon \theta \neq \theta_{0}$, in light of the observed data and
assuming a normal `analysis prior' for the parameter $\theta$ under the
alternative $H_{1}$. In all functions related to the \textit{z}-test Bayes
factor, the normal analysis prior is specified by the prior mean (argument
\texttt{pm}) and the prior standard deviation (argument \texttt{psd}). Setting
the prior standard deviation to zero corresponds to a point prior and reduces
the Bayes factor to a likelihood ratio. As such, the \textbf{bfpwr} package can
also be used for `likelihoodist' (sometimes also known as `evidential') analysis
and design \citep[see e.g.,][for an overview of the likelihoodist/evidential
paradigm]{Royall1997}.

\subsection{Analysis with the \textit{z}-test Bayes factor}
The \textit{z}-test Bayes factor can be calculated using the function
\texttt{bf01}, see \texttt{?bf01} for a detailed description of its arguments.
The following code demonstrates application to data in the form of an estimated
regression coefficient from a logistic regression model and its standard error

\begin{spacing}{1}
<< "bf01-illustration", echo = TRUE >>=
## glm to quantify association between Virginica species and sepal width
iris$virginica <- as.numeric(iris$Species == "virginica")
irisglm <- glm(virginica ~ Petal.Width, data = iris, family = "binomial")
estimate <- summary(irisglm)$coefficients[2,1] # logOR estimate
se <- summary(irisglm)$coefficients[2,2] # standard error

## Bayes factor parameters
null <- 0 # null value
pm <- 0 # analysis prior mean
psd <- 2 # analysis prior sd

## compute z-test Bayes factor
bf01(estimate = estimate, se = se, null = null, pm = pm, psd = psd)
@
\end{spacing}
\noindent We can see that the data provide strong evidence
($\mathrm{BF}_{01} = 1/\Sexpr{round(1/bf01(estimate = estimate, se = se, null = null, pm = pm, psd = psd), 1)}$)
for the alternative hypothesis of a log odds ratio unequal to zero (i.e., an
association between the species Virginica and sepal width), over the null
hypothesis of a log odds ratio equal to zero (i.e., no association). Note that
the Bayes factor calculated using the \texttt{bf01} function and all other
functions in \textbf{bfpwr} are oriented \emph{in favor of the null} hypothesis
over the alternative, so $\mathrm{BF}_{01} > 1$ indicates evidence for the null
hypothesis, whereas $\mathrm{BF}_{01} < 1$ indicates evidence for the
alternative hypothesis. If a Bayes factor orientation in favor of the
alternative over the null is desired instead, one can invert the Bayes factor by
$\mathrm{BF}_{10} = 1/\mathrm{BF}_{01}$.

\subsection{Design with the \textit{z}-test Bayes factor}
Another reason we would want to use \textbf{bfpwr} is that we have no observed
data yet, and we want to either (i) compute a sample size that will produce a
compelling Bayes factor with a given probability, or (ii) compute the
probability of obtaining a compelling Bayes factor for a given sample size (the
`power').

The function \texttt{powerbf01} can be used to compute power and sample size,
assuming that the data are normally distributed and that the parameter of
interest is either a mean or a (standardized) mean difference. It is inspired by
the \texttt{power.t.test} function from the \texttt{stats} package, with which
many users will be familiar. One can either compute the power for a given sample
size (by specifying the \texttt{n} argument) or compute the sample size for a
given power (by specifying the \texttt{power} argument). The code below
demonstrates usage of \texttt{powerbf01} for a two-sample test of a standardized
mean difference parameter

\begin{spacing}{1}
<< "powerbf01-illustration", echo = TRUE >>=
## Bayes factor and sample size parameters
null <- 0 # null value
pm <- 0.3 # analysis prior mean
psd <- 1 # analysis prior sd
k <- 1/10 # desired Bayes factor threshold (BF01 < k)
type <- "two.sample" # two-sample z-test
sd <- 1 # sd of one observation, set to 1 for standardized mean difference scale

## compute sample size to achieve desired power
pow <- 0.9
(res1 <- powerbf01(k = k, power = pow, sd = sd, null = null, pm = pm, psd = psd,
                   type = type))

## compute power for a given sample size
n <- 500
(res2 <- powerbf01(k = k, n = n, sd = sd, null = null, pm = pm, psd = psd,
                   type = type))
@
\end{spacing}

Defining a Bayes factor below the threshold $k = 1/\Sexpr{1/k}$ as target for
compelling evidence, we see that $n = \Sexpr{ceiling(res1[["n"]])}$ observations
per group (obtained from rounding the resulting sample size
$n = \Sexpr{round(res1[["n"]], 2)}$ to the next larger integer) are required to
obtain a power of $\Sexpr{round(pow*100, 1)}$\%, or that a power of
$\Sexpr{round(res2[["power"]]*100, 1)}$\% is obtained for a sample size of
$n = \Sexpr{n}$. Both function calls assume that the underlying parameter is
sampled from the normal analysis prior under the alternative hypothesis, as
specified with the arguments \texttt{pm} and \texttt{psd}. By additionally
specifying the arguments \texttt{dpm} and \texttt{dpsd}, it is also possible to
specify a normal `design prior` that differs from the analysis prior. For
example, we may want to specify a design prior that encodes more optimistic
assumptions about the parameter than the analysis prior, or we may want to set
the design prior to the null hypothesis (\texttt{dpm = null} and \texttt{dpsd =
  0}) to compute the probability of misleading evidence in favor of the
alternative when the null is actually true. The latter is done automatically
when plotting the resulting \texttt{power.bftest} object with the corresponding
\texttt{plot} method, as shown below

\begin{spacing}{1}
<< "plot.powerbf01-illustration", echo = TRUE, fig.height = 6 >>=
## plot power curves (also tweaking the limits and resolution of the x-axis)
plot(res1, nlim = c(1, 3000), ngrid = 1000)
@
\end{spacing}

The first plot highlights the sample size required to achieve the specified
power, along with power values for other sample sizes. The second plot shows a
power curve for obtaining a Bayes factor in favor of the null hypothesis (using
the reciprocal of the specified threshold \texttt{k}), it can be turned off with
the argument \texttt{nullplot = FALSE}. Finally, the argument \texttt{plot =
  FALSE} can be specified to return only the data underlying the plot, for
example, if one wants to use an alternative plotting package.


To conduct such sample size and power calculations for other parameters than a
(standardized) mean (difference), additional assumptions regarding the standard
error and sample size are needed. The functions \texttt{pbf01} and
\texttt{nbf01} can perform power and sample size calculations in more general
cases than \texttt{powerbf01}. Both assume that the standard error is of the
form $\sigma_{\scriptscriptstyle \hat{\theta}}/\sqrt{n}$, where
$\sigma_{\scriptscriptstyle \hat{\theta}}$ is the standard deviation of one
effective observation and $n$ is the `effective sample size'. In both functions,
users have to specify the unit standard deviation
$\sigma_{\scriptscriptstyle \hat{\theta}}$ that determines the scale of the
calculation. Table~\ref{tab:outcomes} lists how some typically used parameters
can be cast into this framework. The documentation of both functions
(\texttt{?pbf01} and \texttt{?nbf01}) provides more information and examples.

\begingroup
\renewcommand{\arraystretch}{1.3} % Default value: 1
\begin{table}[!h]
  \centering
  \caption{Different types of parameter estimates $\hat{\theta}$ with
    approximate standard error
    $\sigma_{\scriptscriptstyle \hat{\theta}}/\sqrt{n}$ and corresponding
    interpretation of sample size $n$ and unit standard deviation
    $\sigma_{\scriptscriptstyle \hat{\theta}}$ (adapted from Chapter 2.4 in
    \citealp{Spiegelhalter2004} and Chapter 1 in \citealp{Grieve2022}). The
    standard deviation of one continuous outcome observation is denoted by
    $\sigma$. Parameter estimates based on two groups assume an equal number of
    observations per group.}
  \label{tab:outcomes}
  \small
  \rowcolors{1}{}{gray!15}
  \begin{tabular}{l l l c}
    \toprule
    \textbf{Outcome} & \textbf{Parameter estimate} $\hat{\theta}$ & \textbf{Interpretation of} $n$ & \textbf{Unit standard deviation} $\sigma_{\scriptscriptstyle \hat{\theta}}$ \\
    \midrule
    Continuous & Mean & Sample size & $\sigma$ \\
    Continuous & Mean difference & Sample size per group & $\sigma\sqrt{2}$ \\
    Continuous & Standardized mean difference & Sample size per group & $\sqrt{2}$ \\
    Continuous & $z$-transformed correlation & Sample size minus 3 & 1 \\
    Binary & Log odds ratio & Total number of events & 2 \\
    Binary & Arcsine square root difference & Sample size per group & $1/\sqrt{2}$ \\
    Survival & Log hazard ratio & Total number of events & 2 \\
    Count & Log rate ratio & Total count & 2 \\

    \bottomrule
    \end{tabular}
\end{table}
\endgroup


\section{\textit{t}-test Bayes factor}
\label{sec:ttest}

The \textit{t}-test Bayes factor is an analysis method specifically tailored to
testing a (standardized) mean (difference) parameter $\theta$ based on normally
distributed data with unknown variance (assumed equal across both groups if more
than one). This Bayes factor quantifies the evidence that the data (in the form
of a \textit{t}-statistic and sample sizes) provide for the null hypothesis that
the parameter equals zero against the alternative hypothesis that it is not
equal zero. Following \citet{Gronau2020}, the \textit{t}-test Bayes factor
implemented in \textbf{bfpwr} assumes that a scale-location \textit{t} prior
distribution (potentially truncated to only positive or only negative
parameters) is assigned to the standardized mean (difference) under the
alternative hypothesis. When centering the prior on zero and setting its degrees
of freedom to one, the Bayes factor reduces to the `Jeffreys-Zellner-Siow' (JZS)
Bayes factor \citep{Jeffreys1961, Zellner1980}, which is often used as a
`default' Bayes factor in the social sciences \citep{Rouder2009}. Setting other
values for these parameters allows data analysts to incorporate directionality
or prior knowledge about the parameter, potentially making the test more
informative. Figure~\ref{fig:tprior} shows examples of different prior
distributions along with the arguments to specify them.

\begin{figure}[!htb]
<< "prior-illustration", fig.height = 3.5, echo = FALSE >>=
tprior <- function(d,
                   plocation = 0,
                   pscale = 1,
                   pdf = 1,
                   alternative = "two.sided") {
    if (alternative == "two.sided") {
        normConst <- 1
        lower <- -Inf
        upper <- Inf
    }
    else if (alternative == "greater") {
        normConst <- 1 - stats::pt(q = (0 - plocation)/pscale, df = pdf)
        lower <- 0
        upper <- Inf
    }
    else {
        normConst <- stats::pt(q = (0 - plocation)/pscale, df = pdf)
        lower <- -Inf
        upper <- 0
    }
    stats::dt(x = (d - plocation)/pscale, df = pdf, ncp = 0)/
        (pscale*normConst)*as.numeric(d >= lower)*as.numeric(d <= upper)
}

dseq <- seq(-3, 3, 0.01)
pars <- data.frame(plocation = c(0, 0, 1), pscale = c(0.7, 0.7, 0.3), pdf = c(1, 1, 30),
                   alternative = c("two.sided", "greater", "two.sided"))
dens <- sapply(X = seq(1, nrow(pars)), FUN = function(i) {
    d <- tprior(d = dseq, plocation = pars$plocation[i], pscale = pars$pscale[i],
                pdf = pars$pdf[i], alternative = pars$alternative[i])
})
cols <- palette.colors(n = 4, alpha = 0.8)[-1]
oldpar <- par(mar = c(4, 5, 2, 2))
matplot(dseq, dens, lty = 1, type = "l", lwd = 1.5, las = 1, col = cols,
        xlab = "Standardized mean difference", ylab = "Prior density",
        panel.first = grid(lty = 3, col = adjustcolor(col = 1, alpha = 0.1)),
        ylim = c(0, 2))
leg <- sapply(X = seq(1, nrow(pars)),
              FUN = function(i) paste(names(pars), pars[i,], sep =  " = ",
                                      collapse = ", ")
              )
legend("topright", legend = leg, col = cols, lwd = 1.5, lty = 1, cex = 0.8)
par(oldpar)
@
\caption{Illustration of different (truncated) scale-location $t$ prior
  distributions for the \textit{t}-test Bayes factor along with the arguments to
  specify them. The yellow and blue priors represent `default' priors that are
  undirectional and directional, respectively, the green prior represents an
  informed prior.}
\label{fig:tprior}
\end{figure}

\subsection{Analysis with the \textit{t}-test Bayes factor}
The \textit{t}-test Bayes factor can be calculated with the function
\texttt{tbf01}, see the documentation \texttt{?tbf01} for details on its
arguments. The following code chunk illustrates usage of the function with two
examples from the literature

\begin{spacing}{1}
<< "tbf01-illustration", echo = TRUE >>=
## paired t-test JZS Bayes factor analyses from Rouder et al. (2009, p.232)
tbf01(t = 2.03, n = 80, plocation = 0, pscale = 1, pdf = 1, type = "paired")

## informed prior analysis from Gronau et al. (2020, Figure 1)
tbf01(t = -0.90, n1 = 53, n2 = 57, plocation = 0.350, pscale = 0.102, pdf = 3,
      alternative = "greater", type = "two.sample")
@
\end{spacing}

The first example reproduces a Bayes factor calculation reported in
\citet[p.~232]{Rouder2009}: A $t$-statistic of $t = 2.03$ obtained from $n = 80$
paired observations part of a psychological experiment, together with a standard
Cauchy distribution assigned to the standardized mean difference parameter (a
$t$ distribution centered around zero with one degree of freedom and a scale of
one), yields a Bayes factor of
$\mathrm{BF}_{01} = \Sexpr{round(tbf01(t = 2.03, n = 80, plocation = 0, pscale = 1, pdf = 1, type = "paired"), 2)}$,
which provides anecdotal evidence in favor of the null hypothesis of no effect
over the alternative hypothesis of an effect. The second example, from
\citet[p.~140-141]{Gronau2020}, analyzes a $t$-statistic of $t = -0.90$ from a
psychological experiment based on a mean comparison of two groups with size
$n_{1} = 53$ and $n_{2} = 57$, respectively. Here, a more informed prior was
elicited from an expert, and is also truncated to positive effects (with the
argument \texttt{alternative = "greater"}). This yields a Bayes factor of
$\mathrm{BF}_{01} = \Sexpr{round(tbf01(t = -0.90, n1 = 53, n2 = 57, plocation = 0.350, pscale = 0.102, pdf = 3, alternative = "greater", type = "two.sample"), 2)}$,
which provides strong evidence for the null hypothesis of no effect over the
alternative of an effect.

\subsection{Design with the \textit{t}-test Bayes factor}
The \texttt{powertbf01} function can be used for both power and sample size
calculations assuming that the future data are analyzed with the \textit{t}-test
Bayes factor, but still assuming known variances and a normal design prior for
the design. As such, the function has a similar specification as
\texttt{powerbf01}, differing only in the arguments of the analysis prior. The
following code illustrates its usage

\begin{spacing}{1}
<< "powertbf01-illustration", echo = TRUE >>=
## determine sample size for a given power
(tres <- powertbf01(k = 1/6, # Bayes factor threshold
                    power = 0.95, # target power
                    type = "two.sample", # two-sample test
                    ## normal design prior
                    dpm = 0.5, # design prior mean at d = 0.5
                    dpsd = 0, # point design prior (standard deviation is zero)
                    ## directional JSZ analysis prior
                    plocation = 0,
                    pscale = 1/sqrt(2),
                    pdf = 1,
                    alternative = "greater"))
@
\end{spacing}

\noindent In this example, taken from \citet[]{Schoenbrodt2017}, it is assumed
that the future data will be analyzed with a two-sample \textit{t}-test Bayes
factor using a directional JSZ analysis prior with a scale of $1/\sqrt{2}$, and
that a Bayes factor below \texttt{k = 1/6} is interpreted as compelling
evidence. In addition, a standardized mean difference of \Sexpr{tres[["dpm"]]}
was assumed for the underlying effect size, which corresponds to setting the
design prior mean to \texttt{dpm = \Sexpr{tres[["dpm"]]}} and its standard
deviation to zero (\texttt{dpsd = \Sexpr{tres[["dpsd"]]}}). If parameter
uncertainty is to be accounted for, one could alternatively set a positive value
for the design prior standard deviation. Taken together, the calculation results
in a sample size of $n = \Sexpr{round(tres[["n"]], 2)}$, which means that at
least \Sexpr{ceiling(tres[["n"]])} observations per group are required to obtain
compelling evidence with a power of \Sexpr{round(100*tres[["power"]], 2)}\%. As
with the \textit{z}-test Bayes factor, the power curves corresponding to these
design calculations can be plotted with

<< "plot-powertbf01-illustration", fig.height = 6 >>=
plot(tres)
@

\section{Normal moment prior Bayes factor}
\label{sec:nonlocal}
The normal moment prior Bayes factor is another analysis method that is
applicable to data in the form of a parameter estimate with standard error,
similar to the \textit{z}-test Bayes factor. The difference between the two
approaches is that the former uses a so-called `normal moment' prior
distribution for the parameter under the alternative hypothesis while the
\textit{z}-test Bayes factor uses just a normal prior distribution. Normal
moment priors are a type of `non-local' prior distribution which allow evidence
for a point null hypothesis to accumulate more quickly if it is indeed true
\citep{Johnson2010}. This is because normal moment priors have zero density at
the null value, see Figure~\ref{fig:nmprior} for an illustration. In all
functions related to the normal moment prior Bayes factor, the prior is
specified by the point null hypothesis (argument \texttt{null}) and the prior
spread (argument \texttt{psd}). The latter controls how much the prior is spread
out, and determines the modes of the distribution which are located at
$\pm \mathtt{psd} \sqrt{2}$. As such, the prior could be specified by setting
the spread parameter so that the modes equal two parameter values deemed
plausible or relevant under the alternative.

\begin{figure}[!tb]
<< "nm-prior-illustration", fig.height = 4, echo = FALSE >>=
dnmoment <- function(x, location = 0, spread = 1) {
    stats::dnorm(x = x, mean = location, sd = spread)*(x - location)^2/spread^2
}
xseq <- seq(-4, 4, length.out = 500)
taus <- c(0.5, 1, 2)
null <- 0
dens <- sapply(X = taus, FUN = function(tau) dnmoment(x = xseq, location = 0, spread = tau))
cols <- hcl.colors(n = length(taus), alpha = 0.8)
oldpar <- par(mar = c(4, 5, 2, 2))
matplot(xseq, dens, type = "l", lty = 1, col = cols, lwd = 1.5,
        xlab = bquote("Parameter" ~ theta), ylab = "Density", las = 1,
        panel.first = grid(lty = 3, col = adjustcolor(col = 1, alpha = 0.1)))
leg <- paste("null = 0, psd =", taus)
legend("topright", legend = leg, col = cols, lty = 1, lwd = 1.5, cex = 0.8,
       bg = "white")
par(oldpar)
@
\caption{Illustration of different normal moment prior distributions along with
  the arguments to specify them.}
\label{fig:nmprior}
\end{figure}

Analysis and design with the normal moment prior Bayes factor is very similar to
analysis with the \textit{z}-test Bayes factor. There is again one analysis
function (\texttt{nmbf01}), a design function for (standardized) mean
(difference) parameters (\texttt{powernmbf01}), and two more general design
functions that can also accommodate other parameter types (\texttt{pnmbf01} and
\texttt{nnmbf01}). The documentation of these functions provides more
information and examples.


% References
\bibliographystyle{apalike}
\bibliography{bibliography}

\newpage
\section*{Computational details}
<< "sessionInfo", echo = TRUE >>=
cat(paste(Sys.time(), Sys.timezone(), "\n"))
sessionInfo()
@

\end{document}
