Advertisement · 728 × 90
#
Hashtag
#RPackageAdvent2025
Advertisement · 728 × 90

Anyways. Lots to explore: new datasets, friendly/informative summary messages of scraped variables, tabling of latent correlations...

Next update will probably be less function-forward. @drmowinckels.io's #RPackageAdvent2025 thread has got me exited about website and documentation improvements.

1 0 2 0
A festive digital illustration features the blue R logo wearing a red Santa hat with white trim on the left. To its right stands a green Christmas tree made entirely of curly braces arranged in a triangular shape. White and light-blue %>% pipe symbols float across a dark blue, starry background like snowflakes. A speech bubble above the R logo says “Ho Ho Ho! 📦” in red text. At the bottom, white text reads: “R Package Development Advent Calendar 2025” and below it, “25 Days of Coding Magic • Dec 1–25.

A festive digital illustration features the blue R logo wearing a red Santa hat with white trim on the left. To its right stands a green Christmas tree made entirely of curly braces arranged in a triangular shape. White and light-blue %>% pipe symbols float across a dark blue, starry background like snowflakes. A speech bubble above the R logo says “Ho Ho Ho! 📦” in red text. At the bottom, white text reads: “R Package Development Advent Calendar 2025” and below it, “25 Days of Coding Magic • Dec 1–25.

My #RPackageAdvent2025 recap is live! 📦✨ Get the complete guide to modern R package development: setup, docs, testing, CI/CD, and CRAN submission. All 25 days of tips, tools, and best practices in one place! Dive in! #RStats #RPackageDevelopment
Link: https://drmo.site/8ny3eU

28 13 0 1
A festive digital illustration features the blue R logo wearing a red Santa hat with white trim on the left. To its right stands a green Christmas tree made entirely of curly braces arranged in a triangular shape. White and light-blue %>% pipe symbols float across a dark blue, starry background like snowflakes. A speech bubble above the R logo says “Ho Ho Ho! 📦” in red text. At the bottom, white text reads: “R Package Development Advent Calendar 2025” and below it, “25 Days of Coding Magic • Dec 1–25.

A festive digital illustration features the blue R logo wearing a red Santa hat with white trim on the left. To its right stands a green Christmas tree made entirely of curly braces arranged in a triangular shape. White and light-blue %>% pipe symbols float across a dark blue, starry background like snowflakes. A speech bubble above the R logo says “Ho Ho Ho! 📦” in red text. At the bottom, white text reads: “R Package Development Advent Calendar 2025” and below it, “25 Days of Coding Magic • Dec 1–25.

Excited to share my R Package Development Advent Calendar 2025 summary! 🎁 All 25 days of modern R pkg dev in one guide. Master `usethis`, GitHub Actions, `pkgdown`, `testthat`, & CRAN prep. Level up your R packages! 🚀 #RStats #RPackageAdvent2025 #Rpkg https://drmo.site/8ny3eU

9 1 0 0
Preview
R Packages (2e) Learn how to create a package, the fundamental unit of shareable, reusable, and reproducible R code.

Your Next Steps:
✨ Apply these tools to your packages
📚 Bookmark for reference
🤝 Share knowledge with community
🚀 Build amazing R packages

Thank you for following #RPackageAdvent2025! Now go make the R ecosystem better! 🎄📦
Keep Learning: r-pkgs.org | usethis.r-lib.org

3 1 2 0
Post image Post image

We Made It! 🎉

25 days. Complete modern R package development workflow. From usethis automation to CRAN submission. You have everything you need!

#rstats #CRAN #RPackageAdvent2025 #ThatsAWrap

33 2 3 1
Post image

Day 25: CRAN Submission Checklist and cran-comments.md

Final steps for successful CRAN submission.

Pro Tip: Be proactive about communicating any unusual aspects of your package to CRAN reviewers.

#rstats #RPackageAdvent2025

6 0 1 0
my_summarise <- function(data, ...) {
  data |>
    dplyr::summarise(...)
}

my_summarise <- function(data, ...) { data |> dplyr::summarise(...) }

my_mutate <- function(data, col, value) {
  data |>
    dplyr::mutate({{ col }} := value)
}

my_mutate <- function(data, col, value) { data |> dplyr::mutate({{ col }} := value) }

my_function <- function(...) {
  dots <- rlang::list2(...)
  # process dots
}

my_function <- function(...) { dots <- rlang::list2(...) # process dots }

Post image

Day 24: rlang - Tidy Evaluation in Packages

Handle user expressions safely in package functions.

Pro Tip: Use {{ }} (embrace) for single arguments, ... for multiple arguments.
Resources: rlang.r-lib.org

#rstats #RPackageAdvent2025

11 0 1 0

Oh wow, that's a neat/powerful idea. Do you have an exemplar of this in action (that's convenient for you to recall)?

I think for our next release I'm just going to be working my way through a bunch of the suggestions in your #RPackageAdvent2025 (pkgdown themes!!!), and this one sounds really cool

0 0 1 0
cli::cli_progress_bar("Processing files", total = length(files))
for (file in files) {
  # process file
  cli::cli_progress_update()
}

cli::cli_progress_bar("Processing files", total = length(files)) for (file in files) { # process file cli::cli_progress_update() }

cli::cli_alert_success("Package built successfully!")
cli::cli_alert_warning("Missing documentation for {.fn my_function}")
cli::cli_abort("Invalid input: {.val {invalid_value}}")

cli::cli_alert_success("Package built successfully!") cli::cli_alert_warning("Missing documentation for {.fn my_function}") cli::cli_abort("Invalid input: {.val {invalid_value}}")

Day 23: cli - Beautiful Command Line Interfaces

Create user-friendly messages and progress indicators.

Pro Tip: Use semantic markup like {.fn function_name} and {.val value} for consistent formatting.
Resources: cli.r-lib.org

#RpackageAdvent2025 #rstats

11 1 0 0
Post image Post image Post image

Day 22: S3, S4, and S7 Object Systems

Create robust object-oriented interfaces with R's object systems.

Pro Tip: Use S3 for simple classes, S4 for complex validation, S7 for modern OOP.
Resources: rconsortium.github.io/S7

#rstats #RPackageAdvent2025

7 3 1 0
Post image Post image Post image

Day 21: rhub - Multi-Platform Testing (Thread)

Test your package on multiple platforms before CRAN submission.

Resources: r-hub.github.io/rhub/

#rstats #RPackageAdvent2025

8 2 1 0
bench::mark(
  my_function(big_data),
  filter_gc = FALSE
)

bench::mark( my_function(big_data), filter_gc = FALSE )

results <- bench::mark(
  old_approach = old_function(data),
  new_approach = new_function(data),
  check = FALSE,  # Skip result equality check
  iterations = 100
)
plot(results)

results <- bench::mark( old_approach = old_function(data), new_approach = new_function(data), check = FALSE, # Skip result equality check iterations = 100 ) plot(results)

Post image

Day 20: Performance Testing with bench

Profile and benchmark your package functions.

Pro Tip: Include benchmarks in your test suite to catch performance regressions.
Resources: bench.r-lib.org

#rstats #RPackageAdvent2025

7 1 2 0
Preview
GitHub - ropensci-review-tools/goodpractice: Advice on R Package Building Advice on R Package Building. Contribute to ropensci-review-tools/goodpractice development by creating an account on GitHub.

Day 19: goodpractice - Package Health Checks

Get comprehensive feedback on package quality

goodpractice::gp()

Checks include:
⬩ Function length and complexity
⬩ Namespace usage
⬩ DESCRIPTION completeness
⬩ Code coverage

Resources: github.com/mangothecat/goodpractice

#rstats #RPackageAdvent2025

9 1 2 0
lintr::lint_package()
styler::style_pkg()

lintr::lint_package() styler::style_pkg()

# .lintr file in project root
linters: linters_with_defaults(
  line_length_linter(120),
  commented_code_linter = NULL
)

# .lintr file in project root linters: linters_with_defaults( line_length_linter(120), commented_code_linter = NULL )

Post image

Day 18: Use linters!

Maintain consistent, readable code style automatically.

Usage:
lintr::lint_package()
styler::style_pkg()

Pro Tip: Add both to pre-commit hooks for automatic code formatting.
Resources: lintr.r-lib.org

#rstats #RPackageAdvent2025

12 3 1 0
# In vignette setup
vcr::use_cassette("demo_data", {
  demo_data <- fetch_api_data("example")
})

# In vignette setup vcr::use_cassette("demo_data", { demo_data <- fetch_api_data("example") })

test_that("API returns expected data", {
  use_cassette("github_api", {
    response <- httr::GET("https://api.github.com/users/octocat")
    expect_equal(httr::status_code(response), 200)
  })
})

test_that("API returns expected data", { use_cassette("github_api", { response <- httr::GET("https://api.github.com/users/octocat") expect_equal(httr::status_code(response), 200) }) })

Post image Post image

Day 17: vcr - Recording API Calls for Tests

Record real API responses for reliable, fast tests without hitting live APIs.

Pro Tip: Commit cassette files to git for reproducible tests across environments.
Resources: docs.ropensci.org/vcr

#rstats #RPackageAdvent2025

1 0 1 0
Post image Post image Post image

Day 16: Testing with Mocks using testthat
Test functions that depend on external resources using testthat's built-in mocking.

Pro Tip: Use local_mocked_bindings() to mock functions within the test scope only.
Resources: testthat.r-lib.org

#rstats #RPackageAdvent2025

2 0 1 0
test_that("plots look right", {
  p <- ggplot(mtcars, aes(mpg, wt)) + geom_point()
  vdiffr::expect_doppelganger("mtcars-scatter", p)
})

test_that("plots look right", { p <- ggplot(mtcars, aes(mpg, wt)) + geom_point() vdiffr::expect_doppelganger("mtcars-scatter", p) })

test_that("error messages are informative", {
  expect_snapshot(my_function(bad_input), error = TRUE)
})

test_that("error messages are informative", { expect_snapshot(my_function(bad_input), error = TRUE) })

Day 15: Snapshot Testing with testthat

Test complex outputs that are hard to specify exactly.

Pro Tip: Review snapshot changes carefully - they capture everything, including whitespace and formatting.

#rstats #RPackageAdvent2025

4 1 1 0
test_that("plot output is stable", {
  p <- my_plot(data)
  vdiffr::expect_doppelganger("basic-plot", p)
})

test_that("plot output is stable", { p <- my_plot(data) vdiffr::expect_doppelganger("basic-plot", p) })

Post image

Day 14: testthat 3rd Edition Features
Modern testing with the latest testthat features.

Setup:
usethis::use_testthat(3)

Pro Tip: Use test_that() with descriptive names that explain what should happen.
Resources: testthat.r-lib.org

#rstats #RPackageAdvent2025

6 1 2 0
usethis::use_github_action("test-coverage")
usethis::use_coverage()  # Adds codecov badge

usethis::use_github_action("test-coverage") usethis::use_coverage() # Adds codecov badge

covr::package_coverage()
covr::report()  
covr::package_coverage() |>
    covr::zero_coverage()

covr::package_coverage() covr::report() covr::package_coverage() |> covr::zero_coverage()

Post image

Day 13: covr - Test Coverage Reporting

Track how much of your code is tested.

use #nocov for code you don't want to cover (like basic R functions etc)

Pro Tip: Focus on testing critical functions thoroughly rather than chasing 100%.
Resources: covr.r-lib.org

#rstats #RPackageAdvent2025

2 0 1 0
- name: Render README
  run: Rscript -e 'rmarkdown::render("README.Rmd")'

- name: Render README run: Rscript -e 'rmarkdown::render("README.Rmd")'

Day 12: README.Rmd Automation

Create dynamic READMEs that stay up-to-date with your code.

Setup:
usethis::use_readme_rmd()

Include these sections:

󠁯•󠁏󠁏 Installation instructions
󠁯•󠁏󠁏 Basic usage example
󠁯•󠁏󠁏 Lifecycle badges
󠁯•󠁏󠁏 Build status badges

#rstats #RPackageAdvent2025

8 2 1 0
# mypackage 1.2.0


## New features
* Added `new_function()` for advanced analysis (#15)


## Bug fixes
* Fixed issue with missing values in `existing_function()` (#12)


## Breaking changes
* `old_param` renamed to `new_param` in `main_function()`

# mypackage 1.2.0 ## New features * Added `new_function()` for advanced analysis (#15) ## Bug fixes * Fixed issue with missing values in `existing_function()` (#12) ## Breaking changes * `old_param` renamed to `new_param` in `main_function()`

Day 11: NEWS.md and Semantic Versioning
Keep users informed about package changes.

Create NEWS.md:
usethis::use_news_md()

Pro Tip: Follow semantic versioning: MAJOR.MINOR.PATCH for breaking.feature.bugfix changes.

#rstats #RPackageAdvent2025

4 0 1 0
#' @lifecycle experimental
new_function <- function() {
  # function body
}

#' @lifecycle experimental new_function <- function() { # function body }

#' @lifecycle deprecated
old_function <- function() {
  lifecycle::deprecate_warn("1.0.0", "old_function()", "new_function()")
  # function body
}

#' @lifecycle deprecated old_function <- function() { lifecycle::deprecate_warn("1.0.0", "old_function()", "new_function()") # function body }

Day 10: lifecycle - Managing Function Deprecation

Communicate changes to users gracefully with lifecycle badges.

Setup:
usethis::use_lifecycle()

Pro Tip: Use lifecycle stages: experimental → stable → superseded → deprecated.
Resources: lifecycle.r-lib.org

#rstats #RPackageAdvent2025

6 1 1 0

Day 9: Vignettes with knitr and rmarkdown

Create comprehensive tutorials and examples for your package.

usethis::use_vignette("getting-started")

● Start with a clear problem statement
● Show realistic examples
● Keep computational time under 5 minutes

#rstats #RPackageAdvent2025

1 0 1 0

I'm also a keen R package developer, and huge fan of the devtools/usethis/r-lib ecosystem which provides the tooling to make package development intuitive, (relatively) easy and joyous.

@drmowinckels.io is currently posting an amazing series on this: check out #RPackageAdvent2025

2 0 1 0
template:
  params:
    bootswatch: flatly

reference:
  - title: "Data manipulation"
    contents:
    - starts_with("mutate")
    - ends_with("_join")

template: params: bootswatch: flatly reference: - title: "Data manipulation" contents: - starts_with("mutate") - ends_with("_join")

Day 8: pkgdown Customization and Deployment

Transform your package documentation into a polished website.

Advanced customization:

Auto-deployment:
usethis::use_github_action("pkgdown")

Pro Tip: Group functions logically in the reference section for better navigation.

#rstats #RPackageAdvent2025

4 0 1 0
Cross-references: 🔗

#' @seealso [other_function()], [pkg::function()]
#' @family utility functions
#' @inheritParams parent_function

Cross-references: 🔗 #' @seealso [other_function()], [pkg::function()] #' @family utility functions #' @inheritParams parent_function

Advanced tags: ⚡

#' @section Warning:
#' This function modifies data in place.
#' 
#' `r paste("Generated on", Sys.Date())` # Run R code

Advanced tags: ⚡ #' @section Warning: #' This function modifies data in place. #' #' `r paste("Generated on", Sys.Date())` # Run R code

Post image

Day 7: roxygen2 Advanced Tags and Cross-References 📝

Master documentation with advanced roxygen2 features, with markdown-style writing! 🎯

💡 Pro Tip: Use @inheritDotParams to inherit ... parameter documentation.
📚 Resources: roxygen2.r-lib.org

#rstats #roxygen2 #Documentation #RPackageAdvent2025

11 0 1 1
Preview
Automate Package and Project Setup Automate package and project setup tasks that are otherwise performed manually. This includes setting up unit testing, test coverage, continuous integration, Git, GitHub, licenses, Rcpp, RStudio…

Let the tool handle the details so you focus on code.
Tomorrow: Advanced roxygen2 for better documentation! 📝

Resources: usethis.r-lib.org
#rstats #usethis #Dependencies #RPackageAdvent2025

2 0 0 0
usethis::use_package("dplyr")

usethis::use_package("data.table", min_version = "1.14.0")

usethis::use_package("ggplot2", type = "Suggests")

usethis::use_package("dplyr") usethis::use_package("data.table", min_version = "1.14.0") usethis::use_package("ggplot2", type = "Suggests")

Post image

Day 6/25: Adding dependencies to your #rstats package 🧵

#rstats #RPackageAdvent2025

The Manual DESCRIPTION Problem: You need to add dplyr to your package. Open DESCRIPTION, find Imports, type "dplyr," hope you didn't typo it, wonder if you need a version constraint, forget to sort alphabetically.

7 0 1 0
template:
  bootstrap: 5

navbar:
  structure:
    left: [intro, reference, articles, tutorials]
    right: [search, github]

template: bootstrap: 5 navbar: structure: left: [intro, reference, articles, tutorials] right: [search, github]

Post image

Day 5: Package Structure with pkgdown Site Generation 🌐
Create beautiful documentation websites for your packages! ✨

usethis::use_pkgdown()
pkgdown::build_site()

💡 Pro Tip: Use usethis::use_pkgdown_github_pages() for deployment.
📚 Resources: pkgdown.r-lib.org

#rstats #RPackageAdvent2025

9 2 1 0
Essential .gitignore entries: 🔒
.Rproj.user
.Rhistory
.RData
.Ruserdata
docs/

Essential .gitignore entries: 🔒 .Rproj.user .Rhistory .RData .Ruserdata docs/

Essential .Rbuildignore entries: 🚫
^.*\.Rproj$
^\.Rproj\.user$
^README\.Rmd$
^LICENSE\.md$
^\.github$
^_pkgdown\.yml$
^docs$
^pkgdown$

Essential .Rbuildignore entries: 🚫 ^.*\.Rproj$ ^\.Rproj\.user$ ^README\.Rmd$ ^LICENSE\.md$ ^\.github$ ^_pkgdown\.yml$ ^docs$ ^pkgdown$

Day 4: .Rbuildignore and .gitignore Best Practices 📁

Control what gets included in your package build and git repository! 🎯

💡 Pro Tip: Use usethis::use_build_ignore() to add entries programmatically.

#rstats #BestPractices #Git #RPackageAdvent2025 🗃️

12 0 1 0