R/plot_volcano.R

Defines functions olink_volcano_plot

Documented in olink_volcano_plot

#' Easy volcano plot with Olink theme
#'
#' @description
#' Generates a volcano plot using the results of the olink_ttest function using
#' ggplot and ggplot2::geom_point. The estimated difference is plotted on the
#' x-axis and the negative 10-log p-value on the y-axis. The horizontal dotted
#' line indicates p-value=0.05. Dots are colored based on the Benjamini-Hochberg
#' adjusted p-value cutoff 0.05 and can optionally be annotated by OlinkID.
#'
#' @param p.val_tbl a data frame of results generated by olink_ttest()
#' @param x_lab Optional. Character value to use as the X-axis label
#' @param olinkid_list Optional. Character vector of proteins (by OlinkID) to
#' label in the plot. If not provided, default is to label all significant
#' proteins.
#' @param ... Optional. Additional arguments for  olink_color_discrete()
#'
#' @return An object of class "ggplot", plotting significance (y-axis) by
#' estimated difference between groups (x-axis) for each protein.
#'
#' @export
#'
#' @examples
#' \donttest{
#' if (rlang::is_installed(pkg = c("broom", "ggrepel"))) {
#'   npx_df <- npx_data1 |>
#'   dplyr::filter(
#'     !grepl(pattern = "control",
#'            x = .data[["SampleID"]],
#'            ignore.case = TRUE
#'
#'      )
#'   )
#'
#'   check_log <- check_npx(df = npx_df)
#'
#'   ttest_results <- OlinkAnalyze::olink_ttest(
#'     df = npx_df,
#'     check_log = check_log,
#'     variable = "Treatment",
#'     alternative = "two.sided"
#'   )
#'
#'   OlinkAnalyze::olink_volcano_plot(
#'     p.val_tbl = ttest_results
#'   )
#' }
#' }
#'
olink_volcano_plot <- function(p.val_tbl, # nolint: object_name_linter
                               x_lab = "Estimate",
                               olinkid_list = NULL,
                               ...) {

  #checking ellipsis
  if (length(list(...)) > 0) {

    ellipsis_variables <- names(list(...))

    if (length(ellipsis_variables) == 1) {

      if (!(ellipsis_variables == "coloroption")) {

        cli::cli_abort(
          c(
            "x" = "The {.arg ...} option only takes the coloroption argument.
            {.arg ...} currently contains the variable
            {.val {ellipsis_variables}}."
          ),
          call = rlang::caller_env(),
          wrap = TRUE
        )

      }

    } else {

      cli::cli_abort(
        c(
          "x" = "The {.arg ...} option only takes one argument. {.arg ...}
          currently contains the variables {.val {ellipsis_variables}}."
        ),
        call = rlang::caller_env(),
        wrap = TRUE
      )
    }
  }

  if (is.null(olinkid_list)) {

    olinkid_list <- p.val_tbl |>
      dplyr::filter(
        .data[["Threshold"]] == "Significant"
      ) |>
      dplyr::pull(
        .data[["OlinkID"]]
      )

  }

  volcano_plot <- ggplot2::ggplot(
    data = p.val_tbl,
    mapping = ggplot2::aes(
      x = .data[["estimate"]],
      y = -log10(.data[["p.value"]]),
      color = .data[["Threshold"]]
    )
  ) +
    ggplot2::geom_point() +
    ggplot2::labs(
      x = x_lab,
      y = "-log10(p-value)"
    ) +
    ggrepel::geom_label_repel(
      data = dplyr::filter(
        p.val_tbl,
        .data[["OlinkID"]] %in%  .env[["olinkid_list"]]
      ),
      mapping = ggplot2::aes(
        label = .data[["Assay"]]
      ),
      box.padding = 1,
      show.legend = FALSE
    ) +
    ggplot2::geom_hline(
      yintercept = -log10(0.05),
      linetype = "dotted"
    ) +
    OlinkAnalyze::set_plot_theme() +
    OlinkAnalyze::olink_color_discrete(...)

  return(volcano_plot)
}

Try the OlinkAnalyze package in your browser

Any scripts or data that you put into this service are public.

OlinkAnalyze documentation built on June 24, 2026, 1:06 a.m.