What’s new in R 4.5.0?
R-bloggers 2025-04-10
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
R 4.5.0 (“How About a Twenty-Six”) was released on 11th April, 2025.Here we summarise some of the interesting changes that have beenintroduced. In previous blog posts we have discussed the new featuresintroduced in R4.4.0 and earlierversions (see the links at the end of this post).
The full changelog can be found at the r-release ‘NEWS’page and ifyou want to keep up to date with developments in base R, have a look atthe r-devel ‘NEWS’page.
Data comes in all shapes and sizes. It can often be difficult to know where to start. Whatever your problem, Jumping Rivers can help.
penguins
Who doesn’t love a new dataset?
One of the great things about learning R for data science is that thereare a collection of datasets available to work with, built into the baseinstallation of R. The Palmer Penguins dataset has been available via anexternalpackagesince 2020, and has been added to R v4.5.0 as a base dataset.
This dataset is useful for clustering and classification tasks and wasoriginally highlighted as an alternative to the iris
dataset.
In addition to the penguins
dataset, there is a related penguins_raw
dataset. This may prove useful when teaching or learning data cleaning.
use()
If you have worked in languages other than R, its approach to importingcode from packages may seem strange. In a Python module, you wouldeither import a package and then use functions from within the explicitnamespace for the package:
import numpynumpy.array([1, 2, 3])# array([1, 2, 3])
Or you would import a specific function by name, prior to its use
from numpy import arrayarray([1, 2, 3])# array([1, 2, 3])
In an R script, we either use explicitly-namespaced functions (withoutloading the containing package):
penguins |> dplyr::filter(bill_len > 40)
Or we load a package, adding all its exported functions to ournamespace, and then use the specific functions we need:
library("dplyr")penguins |> filter(bill_len > 40)
The latter form can cause some confusion. If you load multiple packages,there may be naming conflicts between the exported functions. Indeed,there is a filter()
function in the base package {stats}
that isoverridden when we load {dplyr}
– so the behaviour of filter()
differs before and after loading {dplyr}
.
R 4.5.0 introduces a new way to load objects from a package: use()
.This allows us to be more precise about which functions we load, andfrom where:
# R 4.5.0 (New session)use("dplyr", c("filter", "select"))# Attaching package: ‘dplyr’# # The following object is masked from ‘package:stats’:## filter#penguins |> filter(bill_len > 40) |> select(species:bill_dep)# species island bill_len bill_dep# 1 Adelie Torgersen 40.3 18.0# 2 Adelie Torgersen 42.0 20.2# 3 Adelie Torgersen 41.1 17.6# 4 Adelie Torgersen 42.5 20.7# 5 Adelie Torgersen 46.0 21.5# 6 Adelie Biscoe 40.6 18.6
Note that only those objects that we use()
get imported from thepackage:
# R 4.5.0 (Session continued)n_distinct(penguins)# Error in n_distinct(penguins) : could not find function "n_distinct"
A feature similar to use()
has been available in the{box}
and{import}
packages for a while. {box} is a particularly interesting project, as itallows more fine-grained control over the import and export of objectsfrom specific code files.
Parallel downloads
Historically, the install.packages()
function worked sequentially –both the downloading and installing of packages was performed one at atime. This means it could be slow to install many packages.
We often recommend the{pak}
package forinstalling packages because it can download and install packages inparallel.
But as of R 4.5.0, install.packages()
(and the relateddownload.packages()
and update.packages()
) are capable ofdownloading packages in parallel. This may speed up the wholedownload-and-install process. As described in a post on the R-projectblog by TomasKalibera, the typical speed-up expected is around 2-5x (although this ishighly variable).
C23
C23 is the current standard forthe C language. Much of base R and many R packages require compilationfrom C. If a C23 compiler is available on your machine, R will nowpreferentially use that.
grepv()
For pattern matching in base R, grep()
and related functions are themain tools. By default, grep()
returns the index of any entry in avector that matches some pattern.
penguins_raw$Comments |> grep(pattern = "Nest", x = _)# [1] 7 8 29 30 39 40 69 70 121 122 131 132 139 140 163 164 193 194 199# [20] 200 271 272 277 278 293 294 299 300 301 302 303 304 315 316 341 342
We have been able to extract the values of the input vector, rather thanthe indices, by specifying value = TRUE
in the arguments to grep()
:
penguins_raw$Comments |> grep(pattern = "Nest", x = _, value = TRUE)# [1] "Nest never observed with full clutch." # [2] "Nest never observed with full clutch." # [3] "Nest never observed with full clutch." # [4] "Nest never observed with full clutch." # [5] "Nest never observed with full clutch." # [6] "Nest never observed with full clutch. Not enough blood for isotopes."
Now, in R 4.5.0, a new function grepv()
has been introduced which willautomatically extract values rather than indices from pattern matching:
penguins_raw$Comments |> grepv(pattern = "Nest", x = _)# [1] "Nest never observed with full clutch." # [2] "Nest never observed with full clutch." # [3] "Nest never observed with full clutch." # [4] "Nest never observed with full clutch." # [5] "Nest never observed with full clutch." # [6] "Nest never observed with full clutch. Not enough blood for isotopes."
Contributions from R-Dev-Days
Many of the changes that are described in the “R News” for the newrelease came about as contributions from “R Dev Day”s. These are regularevents that aim to expand the number of people contributing code to thecore of R. In 2024, Jumping Rivers staff attended these events in Londonand Newcastle (priorto “SatRDays” and “Shiny InProduction”,respectively). Dev days are often attached to a conference and providean interesting challenge to anyone interested in keeping R healthy andlearning some new skills.
Trying out R 4.5.0
To take away the pain of installing the latest development version of R,you can use docker. To use the devel
version of R, you can use thefollowing commands:
docker pull rstudio/r-base:devel-jammydocker run --rm -it rstudio/r-base:devel-jammy
Once R 4.5 is the released version of R and the r-docker
repositoryhas been updated, you should use the following command to test out R4.5.
docker pull rstudio/r-base:4.5-jammydocker run --rm -it rstudio/r-base:4.5-jammy
An alternative way to install multiple versions of R on the same machineis using rig
.
See also
The R 4.x versions have introduced a wealth of interesting changes.These have been summarised in our earlier blog posts:
For updates and revisions to this article, see the original post
R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.