Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Package: easybgm
Type: Package
Title: Extracting and Visualizing Bayesian Graphical Models
Version: 0.3.2
Version: 0.4.0
Authors@R: c(
person("Karoline", "Huth", , "k.huth@uva.nl", role = c("aut", "cre"),
comment = c(ORCID = "0000-0002-0662-1591")),
Expand All @@ -10,11 +10,12 @@ Authors@R: c(
person("Gali", "Geller", role = c("ctb"))
)
Maintainer: Karoline Huth <k.huth@uva.nl>
Description: Fit and visualize the results of a Bayesian analysis of networks commonly found in psychology.
The package supports cross-sectional network models fitted using the packages 'BDgraph', 'bgms' and 'BGGM',
as well as network comparison tests fitted using the packages 'bgms' and 'BBGM'.
The package provides the parameter estimates, posterior inclusion probabilities, inclusion Bayes factor, and the
posterior density of the parameters. In addition, for 'BDgraph' and 'bgms' it allows to assess the posterior
Description: Fit and visualize the results of a Bayesian analysis of networks commonly found in psychology.
The package supports cross-sectional network models for ordinal, binary, continuous, and mixed data,
fitted using the packages 'bgms' (default), 'BDgraph', and 'BGGM',
as well as network comparison tests fitted using the packages 'bgms' and 'BGGM'.
The package provides the parameter estimates, posterior inclusion probabilities, inclusion Bayes factor, and the
posterior density of the parameters. In addition, for 'BDgraph' and 'bgms' it allows to assess the posterior
structure space. Furthermore, the package comes with an extensive suite for visualizing results.
License: GPL (>= 2)
URL: https://github.com/KarolineHuth/easybgm
Expand All @@ -28,7 +29,7 @@ Depends:
Imports:
BDgraph,
BGGM,
bgms (>= 0.1.4),
bgms (>= 0.1.6.4),
dplyr,
ggplot2,
HDInterval,
Expand Down
413 changes: 291 additions & 122 deletions R/easybgm.R

Large diffs are not rendered by default.

213 changes: 143 additions & 70 deletions R/easybgm_compare.R
Original file line number Diff line number Diff line change
@@ -1,103 +1,181 @@
#' @title Compare networks across groups using Bayesian inference
#'
#' @description Easy comparison of networks using Bayesian inference to extract differences in conditional (in)dependence across groups.
#'
#' @description Easy comparison of networks using Bayesian inference to extract
#' differences in conditional (in)dependence relations across groups.
#'
#' @name easybgm_compare
#'
#' @param data A list with two n x p matrices or dataframes containing the variables for n independent observations on
#' p variables for two groups. Note that the variables need to be the same in the two different dataframes. Alternatively,
#' when "bgms" version > 0.1.6 is installed, 'data' can also be a matrix of binary and ordinal responses from all groups.
#' If this is the case, the 'group_indicator' argument also needs to be specified.
#' @param type What is the data type? Options: continuous, mixed, ordinal, binary, or blume-capel.
#' @param package The R-package that should be used for fitting the network model; supports BGGM and bgms. Optional argument;
#' default values are specified depending on the datatype.
#' @param not_cont If data-type is mixed, a vector of length p, specifying the not-continuous
#' variables (1 = not continuous, 0 = continuous).
#' @param group_indicator Optional integer vector of group memberships for the rows of the dataframe (multi-group comparison),
#' when data is a matrix instead of a list of two dataframes.
#' @param iter number of iterations for the sampler. Default is 1e3 for data fit with bgms and to 1e4 for data with with BGGM.
#' @param save Logical. Should the posterior samples be obtained (default = TRUE)?
#' @param progress Logical. Should a progress bar be shown (default = TRUE)?
#' @param ... Additional arguments that are handed to the fitting functions of the packages, e.g., informed prior specifications.
#'
#'
#' @return The returned object of \code{easybgm} contains several elements:
#' @param data The data can be provided in two formats:
#'
#' \itemize{
#' \strong{1. A list of two dataframes} (two-group comparison): Each element
#' is an n x p matrix or dataframe for one group. The variables (columns) must
#' be the same across both dataframes. This format is supported by both
#' \code{bgms} and \code{BGGM}.
#'
#' \item \code{parameters} A p x p matrix containing difference across partial associations.
#' \strong{2. A single matrix or dataframe} (multi-group comparison): An n x p
#' matrix containing responses from all groups combined. Requires the
#' \code{group_indicator} argument to specify which rows belong to which
#' group. This format supports two or more groups and is only available with
#' the \code{bgms} package.
#'
#' \item \code{inc_probs} A p x p matrix containing the posterior inclusion probabilities of subgroup differences.
#' @param type Specifies the data type. Currently supported types for group
#' comparison:
#' \itemize{
#' \item \code{"ordinal"}: For ordinal (Likert-type) data. Default package:
#' bgms.
#' \item \code{"binary"}: For binary (0/1) data. Always uses bgms.
#' \item \code{"blume-capel"}: For Blume-Capel ordinal data. Requires
#' \code{baseline_category}. Always uses bgms.
#' \item \code{"continuous"}: Only supported with
#' \code{package = "BGGM"} (must be set explicitly). Not yet supported via
#' bgms.
#' \item \code{"mixed"}: Only supported with
#' \code{package = "BGGM"} (must be set explicitly). Requires
#' \code{not_cont}. Not yet supported via bgms for group comparison.
#' }
#'
#' \item \code{inc_BF} A p x p matrix containing the posterior inclusion Bayes factors of subgroup differences.
#' @param package The R-package used for fitting the comparison model. Optional;
#' if not specified, \code{bgms} is used as the default for ordinal, binary,
#' and blume-capel data. Supported options:
#' \itemize{
#' \item \code{"bgms"} (Default): Supports ordinal, binary, and blume-capel
#' data. Supports both two-group (list input) and multi-group (single
#' dataframe + \code{group_indicator}) comparisons.
#' \item \code{"BGGM"}: Supports continuous and mixed data. Only supports
#' two-group comparison (list input). Binary data is always routed to
#' bgms regardless.
#' }
#'
#' \item \code{structure} Adjacency matrix of the median probability model (i.e., edges with a posterior probability larger 0.5).
#' }
#' @param not_cont A binary vector of length p, required when
#' \code{type = "mixed"}. Each element indicates whether the corresponding
#' variable is not continuous (\code{1} = not continuous/ordinal,
#' \code{0} = continuous).
#'
#' @param group_indicator An integer vector of length n specifying group
#' membership for each row in \code{data}. Required when \code{data} is a
#' single matrix/dataframe (multi-group comparison). Supports two or more
#' groups (e.g., \code{rep(c(1, 2, 3), each = 50)} for three groups of 50
#' observations each). Only available with the \code{bgms} package.
#'
#' @return In addition, for `bgms`, the function returns:
#' @param iter Number of iterations for the sampler. The default depends on the
#' package:
#' \itemize{
#' \item \code{bgms}: 1e4 (10,000 iterations)
#' \item \code{BGGM}: 1e4 (10,000 iterations)
#' }
#' The recommended number of iterations depends on the data and model
#' complexity. Check convergence diagnostics in the output.
#'
#' \itemize{
#' @param save Logical. Should the posterior samples be obtained
#' (default = \code{TRUE})? If \code{TRUE}, the output includes a
#' \code{samples_posterior} matrix with posterior samples for each difference
#' parameter.
#'
#' \item \code{structure_probabilities} A vector containing the posterior probabilities of all visited structures, between 0 and 1.
#' @param progress Logical. Should a progress bar be shown
#' (default = \code{TRUE})?
#'
#' \item \code{graph_weights} A vector containing the number of times a particular structure was visited.
#' @param ... Additional arguments passed to the fitting functions of the
#' underlying packages (e.g., prior specifications). Consult the documentation
#' of \code{bgms} and \code{BGGM} for the specific options available.
#'
#' \item \code{sample_graph} A vector containing the indexes of a particular structure.
#'
#' \item \code{convergence_parameter} A vector containing the R-hat (Gelman–Rubin) statistic for the difference parameter measuring how well MCMC chains have converged to the same target distribution.
#' }
#' @return An object of class \code{easybgm_compare} with the following
#' elements:
#'
#' @return For both packages, when setting `save = TRUE`, the function will also return the following object:
#' \strong{Always returned:}
#' \itemize{
#' \item \code{parameters}: A p x p matrix of posterior mean differences in
#' partial associations across groups.
#' \item \code{inc_probs}: A p x p matrix of posterior inclusion probabilities
#' for group differences (i.e., the probability that an edge differs between
#' groups).
#' \item \code{inc_BF}: A p x p matrix of inclusion Bayes factors for group
#' differences.
#' \item \code{structure}: A p x p adjacency matrix of the median probability
#' model for differences (edges with posterior inclusion probability > 0.5).
#' \item \code{model}: A string indicating the data type used.
#' }
#'
#' \strong{Returned for bgms only:}
#' \itemize{
#' \item \code{structure_probabilities}: Posterior probabilities of all
#' visited graph structures.
#' \item \code{graph_weights}: Number of times each structure was visited.
#' \item \code{sample_graph}: Identifiers for each visited structure.
#' \item \code{convergence_parameter}: The Gelman-Rubin (R-hat) convergence
#' statistic for each difference parameter. Values close to 1 indicate
#' good convergence.
#' }
#'
#' \item \code{samples_posterior} A k x iter matrix containing the posterior samples of parameter differences (i.e., k = (p/(p-1))/2) at each iteration (i.e., iter) of the sampler.

#' \strong{Returned when save = TRUE:}
#' \itemize{
#' \item \code{samples_posterior}: A k x iter matrix of posterior samples for
#' each difference parameter (k = p*(p-1)/2 edges).
#' }
#'
#' @details
#'
#' Users may oftentimes wish to deviate from the default, usually uninformative, prior specifications of the
#' packages to informed priors. This can be done by simply adding additional arguments to the \code{easybgm} function.
#' Depending on the package that is running the underlying network estimation, researcher can specify different prior
#' arguments. Please consult the original packages "bgms" and "BGGM" for the specific informed prior options.
#'
#' We always encourage researcher to conduct prior robustness checks.
#' \strong{Data types and package support for group comparison}
#'
#' \tabular{lcc}{
#' \strong{Data type} \tab \strong{bgms} \tab \strong{BGGM} \cr
#' ordinal \tab Yes (default) \tab No \cr
#' binary \tab Yes (always) \tab No \cr
#' blume-capel \tab Yes (default) \tab No \cr
#' continuous \tab No \tab Yes (explicit)\cr
#' mixed \tab No \tab Yes (explicit)\cr
#' }
#'
#' For continuous or mixed data comparison, you must explicitly set
#' \code{package = "BGGM"}. If no package is specified for these types, the
#' function will return an informative error.
#'
#' \strong{Two-group vs. multi-group comparison}
#'
#' \itemize{
#' \item \strong{Two-group}: Provide \code{data} as a list of two
#' dataframes. Supported by both \code{bgms} and \code{BGGM}.
#' \item \strong{Multi-group}: Provide \code{data} as a single
#' matrix/dataframe and specify \code{group_indicator}. Supports two or more
#' groups. Only available with \code{bgms}.
#' }
#'
#' \strong{Prior specification}
#'
#' Users may wish to adjust priors via the \code{...} argument. Consult the
#' documentation of \code{\link[bgms]{bgm}} and \code{\link[BGGM]{explore}} for
#' specific prior options.
#'
#' We always encourage researchers to conduct prior sensitivity checks.
#'
#' @export
#' @import bgms
#' @importFrom BGGM explore select
#' @importFrom utils packageVersion
#'
#'
#' @examples
#'
#'
#' \donttest{
#' library(easybgm)
#' library(bgms)
#'
#' data <- na.omit(ADHD)
#'
#' # --- Two-group comparison (list input) ---
#' group1 <- data[1:10, 1:3]
#' group2 <- data[11:20, 1:3]
#'
#' # Fitting the Wenchuan PTSD data
#'
#' fit <- easybgm_compare(list(group1, group2),
#' fit <- easybgm_compare(list(group1, group2),
#' type = "binary", save = TRUE,
#' iter = 50 # for demonstration only; more samples required, check the defaults for each sampler
#' iter = 50 # for demonstration only
#' )
#'
#' summary(fit)
#'
#' # For multigroup estimation
#' fit_multi <- easybgm_compare(data[1:200, 1:5],
#'
#' # --- Multi-group comparison (single dataframe + group_indicator) ---
#' fit_multi <- easybgm_compare(data[1:200, 1:5],
#' group_indicator = rep(c(1, 2, 3, 4), each = 50),
#' type = "binary", save = TRUE,
#' iter = 100 # for demonstration only; more samples required, check the defaults for each sampler
#' type = "binary", save = TRUE,
#' iter = 100 # for demonstration only
#' )
#'
#' summary(fit_multi)
#' }

Expand All @@ -116,17 +194,22 @@ easybgm_compare <- function(data,
stop("Your data can't be read. There are two options of providing your data: 1) Provide two datasets in a list containing only the two datasets, or for ordinal data with the bgms pacakge > 0.1.6. 2) provide the data as a matrix or data.frame together with specifying the 'group_indicator' argument, which then also allows for multi-group comparison.",
call. = FALSE)
}
if(type %in% c("continuous", "mixed") && (is.null(package) || package == "bgms")){
stop("Group comparison via bgms currently only supports ordinal and binary data types.
For continuous or mixed data comparison, explicitly set package = 'BGGM'.",
call. = FALSE)
}
if(type == "mixed" & is.null(not_cont)){
stop("Please provide a binary vector of length p specifying the not continuous variables
(1 = not continuous, 0 = continuous).",
call. = FALSE)
}


dots <- list(...)
has_reference <- "reference_category" %in% names(dots)
has_baseline <- "baseline_category" %in% names(dots)

# Example: If type == "blume-capel", then at least one must be present
if (type == "blume-capel" && !(has_reference || has_baseline)) {
stop("For the Blume-Capel model, a reference category needs to be specified.
Expand All @@ -146,8 +229,6 @@ easybgm_compare <- function(data,

# Set default values for fitting if package is unspecified
if(is.null(package)){
if(type == "continuous") package <- "package_bggm_compare"
if(type == "mixed") package <- "package_bggm_compare"
if(type == "ordinal") package <- "package_bgms_compare"
if(type == "binary") package <- "package_bgms_compare"
if(type == "blume-capel") package <- "package_bgms_compare"
Expand All @@ -156,20 +237,12 @@ easybgm_compare <- function(data,
if(package == "bgms") package <- "package_bgms_compare"
if(type == "binary") package <- "package_bgms_compare"
}

# change default number of iterations for BGGM fits
if (iter == 1e3 && package == "package_bgms_compare"){
iter <- 1e4
}

if((package == "package_bgms_compare") & (type %in% c("continuous", "mixed"))){
warning("bgms can only fit ordinal or binary datatypes. For continuous or mixed data,
choose the BGGM package. By default we have changed the package to BGGM",
call. = FALSE)
package <- "package_bggm_compare"

}

if(is.data.frame(data) && package == "package_bggm_compare"){
stop("Your data can't be read. For continuous data fit with BGGM, you can only provide two datasets in a list.",
call. = FALSE)
Expand Down
Loading