# How to Build Interactive Bioinformatics Reports with R Markdown

By the end of this guide you will be able to build a single HTML document that contains your analysis narrative, executable R code, static figures, sortable data tables, and plots that respond to mouse clicks and dropdown menus. You will render it with one command, parameterize it so the same template runs across multiple sample groups, and package it so a collaborator can reproduce every number in it.

Here is what you need installed or on hand before you start:

- R version 4.2 or later from CRAN
- RStudio Desktop (optional but strongly recommended, because its knit button and visual editor save real time)
- The `rmarkdown`, `knitr`, `DT`, and `plotly` R packages
- The `BiocManager` package, which is the standard installer for Bioconductor packages
- A small example dataset. This guide uses the `airway` RNA-seq dataset from Bioconductor, a public dataset of airway smooth muscle cells treated with dexamethasone
- Roughly 4 GB of free disk space if you install the Bioconductor packages listed here

## Why R Markdown Became the Standard for Bioinformatics Reporting

![Decision path asking whether the report must recompute, whether it can be emailed, and which interactivity layer fits.](/article-images/illustrations/interactive-rmarkdown-bioinformatics-interactivity-choice.webp)

Bioinformatics analysis rarely lives in a single script. A typical genomics workflow chains trimming, alignment, quantification, statistical testing, and annotation, where the output of one step feeds the next [1]. Once the heavy computation is done, the analyst faces a second problem: communicating an iterative process of exploration, visualization, and interpretation to collaborators who may not code [2]. R Markdown (with its modern successor Quarto) solves both the communication problem and the record-keeping problem at once, because the document and the analysis that produced it are the same file.

The case for this approach is well documented in the field. Reviewers of bioinformatics practice have noted that scripts and notebooks are excellent for small, single-user analyses but reach their limits for large-scale, shareable pipelines, which is where scientific workflow systems take over [3]. R Markdown sits in the sweet spot for the reporting layer. Mass spectrometry researchers described the alternative as "workflow decay", a state where results are hard to reproduce because they depend on a too-specific computing platform, and argued that standardized infrastructure reduces that decay [4]. Groups building Galaxy-based model pipelines have similarly combined R packages with literate programming tools inside a workflow system to guarantee reproducibility [5], and modern methylation sequencing protocols now embed the entire [statistical analysis](/blog/guides/statistical-analysis) and reporting stage in R as a unified, reproducible pipeline with explicit reporting of intermediate outputs [6].

"Interactive" in this context means three distinct things, and knowing which one you need prevents weeks of wasted effort:

1. **Widget interactivity.** The rendered HTML file contains JavaScript widgets. Readers can sort tables, zoom into plots, and hover for tooltips without a running R session. This works in email attachments, static web servers, and journal supplementary files.
2. **Shiny interactivity.** The document runs a live R session behind a web server. Readers change inputs and the document recomputes. This requires hosting or `rmarkdown::run()`.
3. **App-level interactivity.** A full Bioconductor Shiny application, such as pcaExplorer or the Single-Cell Toolkit, generates an R Markdown report of the user's analysis session as a byproduct, combining a point-and-click experience with a reproducible written record [2] [7].

Most bioinformatics reports should use option 1, with option 2 reserved for genuinely exploratory deliverables. The walkthrough below builds option 1 first, then adds option 2.

## Step-by-Step Walkthrough: Interactive R Markdown Bioinformatics from a Blank Directory

### Step 1. Install the Toolchain

Open an R console and run:

```r
install.packages(c("rmarkdown", "knitr", "DT", "plotly", "htmlwidgets"))

if (!require("BiocManager", quietly = TRUE))
    install.packages("BiocManager")

BiocManager::install(c("airway", "DESeq2", "pcaExplorer", "GeneTonic"))
```

Expected output: a stream of download progress bars, then `The downloaded source packages are in ...` for the CRAN packages and `Bioconductor version 3.x (BiocManager x.x)` confirmation for the Bioconductor set. Verify the install:

```r
packageVersion("rmarkdown")   # e.g. '2.29'
packageVersion("DESeq2")      # e.g. '1.44.0'
rmarkdown::pandoc_version()   # e.g. '3.1.11'
```

If `pandoc_version()` returns an error, see the troubleshooting section below. Recording package versions here is not cosmetic. Large multi-institution workflows succeed precisely because every processing step, including software versions, is pinned and documented [1], and protocols for targeted methylation sequencing make harmonized parameterization an explicit best practice [6].

### Step 2. Create the Project and the R Markdown Skeleton

In RStudio, choose File, New Project, New Directory. Then create a file named `report.Rmd`. Start with this skeleton:

```yaml
---
title: "Airway [RNA-seq Differential Expression](/knowledge/bioinformatics/rna-seq-differential-expression-deseq2-edger) Report"
author: "Your Name"
date: "`r Sys.Date()`"
output:
  html_document:
    theme: flatly
    toc: true
    toc_depth: 2
    toc_float: true
    code_folding: show
    self_contained: true
params:
  contrast: "dex_alb_vs_alb"
  padj_cutoff: 0.05
---
```

Each field matters:

| Field | What it controls | Why it matters for bioinformatics |
|--|--|--|
| `output: html_document` | The rendered format. `self_contained: true` inlines images and widgets into one file | A single HTML file travels by email and works offline |
| `toc_float: true` | A clickable table of contents pinned to the side | Collaborators navigate a 20-section QC report without scrolling |
| `code_folding: show` | Code blocks start visible, with a hide toggle | Reviewers can see the code, managers can hide it |
| `params:` | Values you can override at render time | One template, many sample groups or contrasts |
| `padj_cutoff` | The adjusted p-value threshold as a parameter | Reviewers can rerun the report at 0.01 without editing code |

The `params` block is the single highest-leverage feature for anyone learning how to use R Markdown for interactive bioinformatics reports. It turns a one-off analysis into a reusable template.

### Step 3. Set Global Chunk Options

Immediately after the YAML header, add a setup chunk:

```{r setup, include=FALSE}
knitr::opts_chunk$set(
  echo = TRUE,
  warning = FALSE,
  message = FALSE,
  fig.width = 7,
  fig.height = 5,
  cache = TRUE,
  cache.extra = file.mtime("counts.rds")
)
```

The `cache = TRUE` option stores chunk results between renders, which matters when your document reads large count matrices or runs differential expression. The `cache.extra` line invalidates the cache whenever the input file changes, which prevents the most common reproducibility bug in cached reports (covered in the mistakes section). Set `echo = FALSE` later for client-facing versions, keeping `echo = TRUE` for internal audit versions.

### Step 4. Load Data and Run the Core Analysis in a Chunk

This chunk performs a minimal differential expression analysis on the airway dataset, following the standard DESeq2 design:

```{r analysis, cache=TRUE}
library(DESeq2)
library(airway)

data("airway")
se <- airway

dds <- DESeqDataSet(se, design = ~ cell + dex)
dds$dex <- relevel(dds$dex, ref = "untrt")
dds <- DESeq(dds)
res <- results(dds, contrast = c("dex", "trt", "untrt"))

# Save intermediate results so the report documents its provenance
saveRDS(res, "results_de.rds")

summary(res)
```

Expected output in the rendered report:

```
out of 21816 with nonzero total read count
adjusted p-value < 0.1
LFC > 0 (up)    : 1,816, 8.3%
LFC < 0 (down)  : 2,344, 10.7%
outliers [1]    : 0, 0%
low counts [2]  : 9,297, 43%
(mean count < 11)
```

Your exact numbers may differ slightly by DESeq2 version. This is normal and is another reason to print `sessionInfo()` in the report (Step 9).

### Step 5. Add the First Interactive Widget: A Sortable Results Table

The base R way to show results is `head(res)`. The interactive way is `DT::datatable()`, which renders a JavaScript data table with search, sorting, and pagination, all inside the static HTML file:

```{r results-table}
library(DT)
res_df <- as.data.frame(res)
res_df$gene <- rownames(res_df)

datatable(
  res_df,
  extensions = "Buttons",
  options = list(
    pageLength = 10,
    dom = "Bfrtip",
    buttons = c("csv")
  ),
  rownames = FALSE
) |>
  formatRound(columns = c("log2FoldChange", "padj"), digits = 4)
```

Expected output: a table with a search box, column sort arrows, page controls, and a "Copy" and "CSV" button. The reader can type "DUSP1" into the search box and instantly see that gene's log2 fold change and adjusted p-value. In interactive rmarkdown bioinformatics practice, this one substitution replaces most of the Excel files that would otherwise circulate alongside a report.

### Step 6. Add Plot Interactivity with ggplotly

Any `ggplot2` figure becomes zoomable and hoverable by wrapping it in `plotly::ggplotly()`:

```{r volcano, cache=TRUE}
library(ggplot2)

volcano_df <- data.frame(
  lfc = res_df$log2FoldChange,
  padj = res_df$padj,
  gene = res_df$gene
)
volcano_df$call <- with(volcano_df,
  ifelse(is.na(padj), "NA",
    ifelse(padj < params$padj_cutoff & abs(lfc) > 1, "sig",
      "ns")))

p <- ggplot(volcano_df[volcano_df$call != "NA", ],
            aes(x = lfc, y = -log10(padj), color = call, text = gene)) +
  geom_point(alpha = 0.4, size = 1.2) +
  scale_color_manual(values = c(ns = "grey60", sig = "#C0392B")) +
  labs(x = "log2 fold change (dex vs untrt)",
       y = "-log10 adjusted p-value") +
  theme_minimal()

plotly::ggplotly(p, tooltip = c("text", "x", "y"))
```

Expected output: a plot with mode bar icons at the top (zoom, box select, pan, download as PNG). Hovering a point shows the gene symbol, fold change, and p-value. Note the `text = gene` aesthetic, which is what makes the tooltip informative. Without it, `ggplotly` shows only raw x and y coordinates, which is nearly useless for a volcano plot.

Keep a static `ggplot2` version of the same figure as well, either via a chunk with `eval = FALSE` for the interactive layer, or by writing the static figure to file with `ggsave()`. Static versions are safer for print and for journals that reject embedded JavaScript.

### Step 7. Parameterize and Render Programmatically

Render from the R console rather than clicking Knit when you need repeatability:

```r
rmarkdown::render(
  "report.Rmd",
  output_file = paste0("airway_report_", params_contrast, ".html"),
  params = list(
    contrast = "dex_trt_vs_untrt",
    padj_cutoff = 0.01
  ),
  envir = new.env(parent = globalenv())
)
```

Expected output: a progress line per chunk (`processing file: report.Rmd`, then chunk names `setup`, `analysis`, `results-table`, `volcano`), followed by `output file: airway_report_dex_trt_vs_untrt.html`. The `envir = new.env(...)` argument gives each render a clean memory space, which prevents leakage between parameterized runs when you loop over contrasts:

```r
contrasts <- list(list(contrast = "trt_vs_untrt", padj_cutoff = 0.05),
                  list(contrast = "trt_vs_untrt", padj_cutoff = 0.01))

for (p in contrasts) {
  rmarkdown::render("report.Rmd",
    output_file = paste0("report_padj", p$padj_cutoff, ".html"),
    params = p)
}
```

This pattern, one template rendered under many parameter sets, is the reporting-layer equivalent of the modular pipelines used across large-scale bioinformatics, where modular design allows tool substitution and adaptation [3] [6].

### Step 8. Add a True Shiny Runtime (Optional Layer)

When the deliverable is exploration rather than a record, add `runtime: shiny` to the YAML header. The document then needs a live R process:

```yaml
runtime: shiny
```

And a reactive block:

```{r shiny-interactive, eval=FALSE}
library(shiny)
inputPanel(
  selectizeInput("gene", "Gene of interest:",
                 choices = head(res_df$gene, 500)),
  sliderInput("lfc", "Min |log2 FC|:", min = 0, max = 4, value = 1)
)

renderPlot({
  d <- volcano_df[abs(volcano_df$lfc) >= input$lfc, ]
  highlight <- d$gene == input$gene
  plot(d$lfc, -log10(d$padj), pch = 19, cex = 0.6,
       col = ifelse(highlight, "red", "grey70"),
       xlab = "log2 FC", ylab = "-log10 padj")
  if (any(highlight)) abline(h = -log10(d$padj[highlight]), lty = 2)
})
```

Expected output: a dropdown menu and slider above a live-updating plot inside the rendered document. Preview it with `rmarkdown::run("report_shiny.Rmd")`, which launches a local Shiny server in your browser. The key distinction: a Shiny document recomputes from the reader's browser, so it cannot be emailed as a static artifact, whereas the widget-based document from Steps 5 and 6 can.

### Step 9. Close the Loop with a Full Interactive Session and a Generated Report

The strongest form of interactive rmarkdown bioinformatics practice combines point-and-click analysis with automatic report generation. The Bioconductor packages pcaExplorer, ideal, and GeneTonic provide Shiny applications for RNA-seq exploratory data analysis, statistical testing review, and functional enrichment, and each documents the performed steps with R Markdown to guarantee reproducibility [2]. In pcaExplorer, run:

```r
library(pcaExplorer)
library(DESeq2)
pcaExplorer(dds = dds, dst = res)
```

A browser window opens with interactive PCA, sample-to-sample distance heatmaps, and gene-level drilldowns. The application includes a report-generation feature that captures your session's analysis into an R Markdown document, so the analyst's clicks become a reproducible narrative [2]. The same pattern exists in single-cell analysis. The Single-Cell Toolkit 2 (SCTK2) exposes scRNA-seq workflows through an R/Shiny graphical interface for non-computational users, and HTML reports generated with R Markdown document and recapitulate individual steps or entire workflows [7]. Longitudinal metabolomics tools follow the same design, retaining all intermediate results and provenance within a container and producing reproducible HTML or PDF outputs automatically [8].

For your own reports, finish every document with a provenance chunk:

```{r session, echo=TRUE}
sessionInfo()
```

Expected output: R version, locale, and the full attached package list with versions. This is the cheapest reproducibility insurance available, and it aligns with the practice of reporting intermediate outputs explicitly so that others can audit each analytical stage [6].

### Step 10. Verify the Report Is Correct

Check four things before sending any report to a collaborator:

1. **Re-render from scratch.** Delete the `*_cache` and `*_files` directories, close all R sessions, and render once. The numbers should not change. If they do, the document depends on hidden session state.
2. **Check the params.** Open the rendered HTML and confirm the reported threshold matches the `params$padj_cutoff` value used in the render command, not the default in the YAML.
3. **Check widget degradation.** Open the HTML with JavaScript disabled or in a plain viewer. The static `ggplot2` fallback and the printed table should still convey the result.
4. **Verify file size.** A `self_contained` document embedding many Plotly figures can exceed 50 MB. If it does, set `self_contained: false` and ship the `_files` folder alongside, or reduce the number of interactive figures.

## Troubleshooting Exact Errors

**Error: "pandoc version 1.12.3 or higher is required and was not found"** (from `rmarkdown::render()`). This means R cannot find Pandoc. In RStudio this is rare because RStudio bundles Pandoc. From a plain terminal or an HPC module environment, install Pandoc from the official repository or load the module (`module load pandoc` on many clusters), then re-run.

**Error: "there is no package called 'DESeq2'"**. The Bioconductor package was never installed, or you are in a different library path. Run `BiocManager::install("DESeq2")` and check `.libPaths()` to confirm which library R is actually using.

**Error: "object 'res' not found" in a later chunk.** An earlier chunk was skipped, usually because `cache = TRUE` reused a stale cache from a run where the chunk errored. Delete the cache directory for that chunk (found under `_cache/report/`) or run `knitr::clean_cache()`, then re-render.

**Error: "Error in eval(expr, envir, enclos): object 'params' not found"**. The YAML `params:` block is missing or malformed (wrong indentation, missing colon). Params must be top-level in the YAML, indented two spaces under `params:`.

**Warning: "It seems you are calling the shinyInput function from a code chunk..."** or a blank widget area. Widgets fail silently when `self_contained: true` meets very large widget payloads, or when the HTML is viewed from a `file://` URL with strict browser settings. Test in Chrome or Firefox, and split large documents if widgets disappear.

**Error: "An error occurred during the render: 'attempt to apply non-function'"**. Usually a masked function, for example `filter` from a package other than `dplyr`. Qualify calls explicitly (`dplyr::filter()`) throughout report code. This costs nothing and removes an entire class of render failures.

## Interactive R Markdown Bioinformatics Tips That Save Hours

- **Precompute, do not recompute.** Widgets should wrap finished results. Differential expression belongs in a cached chunk, the volcano plot draws from the saved data frame. A Shiny runtime that reruns DESeq2 on every slider move will feel broken. This mirrors the division of labor in established pipelines, where heavy preprocessing runs in dedicated stages and the R layer handles statistics and reporting [6].
- **Split by document size, not by topic.** If a report exceeds roughly 10 MB of embedded widgets, split the QC section from the results section. Render both from the same params.
- **Use `ref.label` for the audit/client split.** Write two versions of a chunk (verbose and clean), label them, and include only the right one per output via a parameter.
- **Pin Bioconductor versions in CI.** When a report must survive months, render it with a fixed Bioconductor release. The infrastructure literature on multi-site genomics workflows emphasizes that portability across heterogeneous environments depends on pinning every software layer [1].
- **Steal the two-panel pattern.** pcaExplorer and GeneTonic pair each interactive panel with the equivalent static R Markdown output, so readers who cannot or will not use the browser interface still get the full result [2]. Adopt the same pairing in your reports.
- **Know when to leave R Markdown.** If the report is one artifact inside a multi-sample production flow that runs on a cluster, wrap the render step inside a workflow system rather than growing the document itself. Reviews of pipeline practice describe this boundary explicitly: scripting and notebooks serve small-scale analyses, scientific workflow systems serve large-scale, reusable pipelines [3] [9].

## Common Mistakes and Limitations

**Caching without `cache.extra`.** Cached chunks do not see upstream changes to your count matrix or metadata. The report renders instantly, looks correct, and reports last month's result. Always attach a cache invalidation key tied to input file timestamps or checksums.

**Interactive widgets as the only representation of a result.** A Plotly figure is invisible to screen readers in many contexts, cannot be printed faithfully, and fails in some PDF conversions. Every interactive figure should have a static twin for the record. This is the same principle behind protocols that report intermediate outputs explicitly at each stage, so transparency survives the tooling [6].

**Confusing parameterized reports with a pipeline.** Rendering one template across ten contrasts is not a pipeline. There is no dependency tracking, no restart-from-failure, no provenance graph. Reviews of workflow reuse find that ad hoc scripts scale poorly and that workflow systems exist precisely to provide modularity, reproducibility, and reusability beyond what notebooks offer [3]. Use R Markdown for the human-readable analysis and reporting layer, and Nextflow, Snakemake, or Galaxy for orchestration, as TCGA-scale projects do with a Nextflow workflow coordinating download, preprocessing, and network inference in a single command [9].

**Heavy computation inside the document.** A document that aligns reads or runs full-cell clustering will take hours per render and will not cache reliably across package updates. Precompute to `Rds` or `HDF5` artifacts in a separate pipeline, and let the report read them. Group-built genomics workflows separate computationally intensive processing steps from downstream analysis for exactly this reason [1].

**Ignoring session state during interactive development.** Knitting runs all chunks in a fresh session in order, but your interactive RStudio session carries hidden state. Code that knits cleanly may fail interactively and vice versa. When a chunk fails only in Knit, suspect a variable defined in the console but not in any chunk.

**Shipping a Shiny document when the reader wanted a file.** `runtime: shiny` documents cannot be opened offline. If the deliverable is email-able, stick to widgets.

**Forgetting the reader's browser.** Very old browsers and some institutional environments block inline JavaScript. Ask your audience once, before building, whether their environment renders widgets. Where it does not, the workflow-decay lesson applies: a result that depends on a too-specific platform stops being used, so standardize on what the audience can actually open [4].

**One case-specific limitation to state plainly:** this article teaches a document and reporting method. It does not interpret any biological result for you, and individual study design, sample sizing, and clinical interpretation need input from a statistician and a domain expert, not from a template.

## Frequently Asked Questions

### Do I need Shiny to make an R Markdown report interactive?

No. The `DT` and `plotly` packages add search, sorting, zoom, and hover to a static HTML file with no running R session. Shiny is only necessary when the report must recompute in response to reader input.

### Can R Markdown reports be part of a formal bioinformatics pipeline?

Yes, as the reporting layer. Heavy processing stages should live in a workflow system such as Nextflow or Snakemake, with the R Markdown document consuming the pipeline's outputs and being rendered by the pipeline itself.

### How do I handle very large datasets in a report?

Precompute all statistics and store compact artifacts (results tables, PCA coordinates, per-gene summaries) as Rds files, and have the report load only those artifacts. Never put genome-scale computation inside a chunk that re-executes on every render.

### What is the difference between an htmlwidget and a Shiny document?

![Side by side comparison of htmlwidget and Shiny documents across runtime, offline use, email and recompute.](/article-images/illustrations/interactive-rmarkdown-bioinformatics-widget-vs-shiny.webp)

An htmlwidget is JavaScript embedded in the finished HTML, it works offline and needs no server. A Shiny document has `runtime: shiny` in its YAML, requires a live R process, and recomputes on the server when the reader changes inputs.

### How do I make my report reproducible for reviewers?

Print `sessionInfo()`, pin package versions, record all parameter values in the document, re-render from a clean environment with no cache, and archive the input data with the report. Bioconductor-based interactive tools follow this same pattern by documenting performed steps with R Markdown [2].

### Which Bioconductor packages generate reports automatically?

pcaExplorer, ideal, and GeneTonic for RNA-seq exploratory analysis, differential expression review, and functional enrichment, and SCTK2 for single-cell RNA-seq. Each runs as a Shiny app and produces an R Markdown-based HTML report of the session [7].

### Can I render the same report for multiple samples or contrasts?

Yes. Define a `params:` block in the YAML and call `rmarkdown::render()` in a loop, passing different values and distinct `output_file` names for each run. Every rendered file then carries its own parameter set in the reproducible record.

### Why does my cached report show stale results after I updated the data?

Chunk caching stores results keyed by the chunk code, not by your data files. Add `cache.extra = file.mtime("your_input_file")` (or a checksum) to the chunk options so the cache invalidates whenever the input changes.

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "FAQPage",
  "mainEntity": [
    {
      "@type": "Question",
      "name": "Do I need Shiny to make an R Markdown report interactive?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "No. The DT and plotly packages add search, sorting, zoom, and hover to a static HTML file with no running R session. Shiny is only necessary when the report must recompute in response to reader input."
      }
    },
    {
      "@type": "Question",
      "name": "Can R Markdown reports be part of a formal bioinformatics pipeline?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Yes, as the reporting layer. Heavy processing stages should live in a workflow system such as Nextflow or Snakemake, with the R Markdown document consuming the pipeline's outputs and being rendered by the pipeline itself."
      }
    },
    {
      "@type": "Question",
      "name": "How do I handle very large datasets in a report?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Precompute all statistics and store compact artifacts such as results tables, PCA coordinates, and per-gene summaries as Rds files, and have the report load only those artifacts. Never put genome-scale computation inside a chunk that re-executes on every render."
      }
    },
    {
      "@type": "Question",
      "name": "What is the difference between an htmlwidget and a Shiny document?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "An htmlwidget is JavaScript embedded in the finished HTML, it works offline and needs no server. A Shiny document has runtime shiny in its YAML, requires a live R process, and recomputes on the server when the reader changes inputs."
      }
    },
    {
      "@type": "Question",
      "name": "How do I make my report reproducible for reviewers?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Print sessionInfo(), pin package versions, record all parameter values in the document, re-render from a clean environment with no cache, and archive the input data with the report. Bioconductor-based interactive tools follow this same pattern by documenting performed steps with R Markdown."
      }
    },
    {
      "@type": "Question",
      "name": "Which Bioconductor packages generate reports automatically?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "pcaExplorer, ideal, and GeneTonic for RNA-seq exploratory analysis, differential expression review, and functional enrichment, and SCTK2 for single-cell RNA-seq. Each runs as a Shiny app and produces an R Markdown-based HTML report of the session."
      }
    },
    {
      "@type": "Question",
      "name": "Can I render the same report for multiple samples or contrasts?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Yes. Define a params block in the YAML and call rmarkdown::render() in a loop, passing different values and distinct output_file names for each run. Every rendered file then carries its own parameter set in the reproducible record."
      }
    },
    {
      "@type": "Question",
      "name": "Why does my cached report show stale results after I updated the data?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Chunk caching stores results keyed by the chunk code, not by your data files. Add cache.extra = file.mtime() of the input file, or a checksum, to the chunk options so the cache invalidates whenever the input changes."
      }
    }
  ]
}
</script>

## Sources

1. [Developing reproducible bioinformatics analysis workflows for heterogeneous computing environments to support African genomics.](https://pubmed.ncbi.nlm.nih.gov/30486782/)
2. [Interactive and Reproducible Workflows for Exploring and Modeling RNA-seq Data with pcaExplorer, Ideal, and GeneTonic.](https://pubmed.ncbi.nlm.nih.gov/35467799/)
3. [Developing and reusing bioinformatics data analysis pipelines using scientific workflow systems.](https://pubmed.ncbi.nlm.nih.gov/36968012/)
4. [An evolving computational platform for biological mass spectrometry: workflows, statistics and data mining with MASSyPup64.](https://pubmed.ncbi.nlm.nih.gov/26618079/)
5. [GCAC: galaxy workflow system for predictive model building for virtual screening.](https://pubmed.ncbi.nlm.nih.gov/30717669/)
6. [A Guide to Enzymatic Targeted Methylation Sequencing Bioinformatics Workflow: Best Practices.](https://pubmed.ncbi.nlm.nih.gov/42848382/)
7. [Interactive analysis of single-cell data using flexible workflows with SCTK2.](https://pubmed.ncbi.nlm.nih.gov/37602214/)
8. [MeTime: an R package for reproducible longitudinal metabolomics data analysis.](https://pubmed.ncbi.nlm.nih.gov/42730207/)
9. [Reproducible processing of TCGA regulatory networks.](https://pubmed.ncbi.nlm.nih.gov/41114645/)