Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
R is known for its versatility and extensive collection of packages. As of the publishing of this post, there are over 23 thousand packages on R-universe. But what if I told you that you could do some pretty amazing things without loading any packages at all?
There’s a lot of love for base R, and I am excited to pile on. In this blog post, we will explore a few of my favorite “not-so-basic” (i.e., maybe new to you!) base R functions. Click ‘Run code’ in order to see them in action, made possible by webR and the quarto-webr extension!1
- invisible(): Return an invisible copy of an object
- noquote(): Print a character string without quotes
- coplot(): Visualize interactions
- nzchar(): Find out if elements of a character vector are non-empty strings
- with(): Evaluate an expression in a data environment
- Null coalescing operator
%||%
: Return first input if notNULL
, otherwise return second input
1. invisible
The invisible()
function “returns a temporarily invisible copy of an object” by hiding the output of a function in the console. When you wrap a function in invisible()
, it will execute normally and can be assigned to a variable or used in other operations, but the result isn’t printed out.
Below are examples where the functions return their argument x
, but one does so invisibly.
The way to see invisible output is by saving to a variable or running print()
. Both of the below will print:
Let’s try another example. Run the chunk below to install the purrr and tidytab packages. Installing the CRAN version of purrr from the webR binary repository is as easy as calling webr::install()
. The tidytab package is compiled into a WebAssembly binary on R-universe and needs the repos
argument to find it. mount = FALSE
is due to a bug in the Firefox WebAssembly interpreter. If you’re not using Firefox, then I suggest you try the code below with mount = TRUE
! (Note: this might take a few seconds, and longer with mount = FALSE
.)
Using purrr and tidytab::tab2()
together results in two NULL
list items we do not need.
Running invisible()
eliminates that!
When writing a function, R can print a lot of stuff implicitly. Using invisible()
, you can return results while controlling what is displayed to a user, avoiding cluttering the console with intermediate results.
Per the Tidyverse design guide, “if a function is called primarily for its side-effects, it should invisibly return a useful output.” In fact, many of your favorite functions use invisible()
, such as readr::write_csv()
, which invisibly returns the saved data frame.
2. noquote
The noquote()
function “prints character strings without quotes.”
Resources
I use noquote()
in a function url_make
that converts Markdown reference-style links into HTML links. The input is a character string of a Markdown reference-style link mdUrl
and the output is the HTML version of that URL. With noquote()
, I can paste the output directly in my text.
Very proud of my little #rstats function to turn a Markdown URL to HTML ☺️ (and save it to your clipboard too). pic.twitter.com/TsddtTDn9R
— Isabella Velásquez (@ivelasq3) April 27, 2022
Try it out in an anonymous function below!
Learn more about this syntax in my previous blog post!
3. coplot
The coplot()
function creates conditioning plots, which are helpful in multivariate analysis. They allow you to explore pairs of variables conditioned on a third so you can understand how relationships change across different conditions.
The syntax of coplot()
is coplot(y ~ x | a, data)
, where y
and x
are the variables you want to plot, a
is the conditioning variable, and data
is the data frame. The variables provided to coplot()
can be either numeric or factors.
Using the built-in quakes
dataset, let’s look at the relationship between the latitude (lat
) and the longitude (long
) and how it varies depending on the depth in km of seismic events (depth
).
To interpret this plot:
- Latitude is plotted on the y-axis
- Longitude is plotted on the x-axis
- The six plots show the relationship of these two variables for different values of depth
- The bar plot at the top indicates the range of depth values for each of the plots
- The plots in the lower left have the lowest range of depth values and the plots in the top right have the highest range of depth values
The orientation of plots might not be the most intuitive. Set rows = 1
to make the coplot easier to read.
Here, you can see how the area of Fiji earthquakes grows smaller with increasing depth.
You can also condition on two variables with the syntax coplot(y ~ x| a * b)
, where the plots of y
versus x
are produced conditional on the two variables a
and b
. Below, the coplot shows the relationship with depth from left to right and the relationship with magnitude (mag
) from top to bottom. Check out a more in-depth explanation of this plot on StackOverflow.
I first learned about coplot()
thanks to Eric Leung’s tweet. Thanks, Eric!
TIL about coplots in base #RStats. in my nearly decade use of R, i've never come across this function to quickly explore pairs of variables conditioned on a third
— Eric Leung 梁挺亮 (@erictleung) August 5, 2022
library(palmerpenguins)
coplot(body_mass_g ~ bill_length_mm|species, data = penguins)https://t.co/EVpI738VzO pic.twitter.com/zcTw4HGvnZ
4. nzchar
From the documentation, “nzchar()
is a fast way to find out if elements of a character vector are non-empty strings”. It returns TRUE
for non-empty strings and FALSE
for empty strings. This function is particularly helpful when working with environment variables - see an example in the tuber documentation!
Resources
I have written about nzchar in the past and I’ve also explained how to create a GIF using asciicast!
TIL: nzchar(). Super useful when working with environment variables in R.
— Isabella Velásquez (@ivelasq3) May 11, 2022
also, #asciicast is amazing! install the GIF converter with remotes::install_github('r-lib/asciicast', ref = remotes::github_pull(24)) #rstats h/t @GaborCsardi pic.twitter.com/pCZQLCNaDl
5. with
If you use base R, you’ve likely encountered the dollar sign $
when evaluating expressions with variables from a data frame. The with()
function lets you reference columns directly, eliminating the need to repeat the data frame name multiple times. This makes your code more concise and easier to read.
So, instead of writing plot(mtcars$hp, mtcars$mpg)
, you can write:
This is particularly handy to use with the base R pipe |>
:
Michael Love’s Tweet shows how to connect a dplyr chain to a base plot function using with()
:
6. lengths
lengths()
is a more efficient version of sapply(df, length)
. length()
determines the number of elements in an object, and lengths()
will provide the lengths of elements across columns in the data frame.
Pretty straightforward but I think it is a neat function 🙂
< section id="null-coalescing-operator-in-r" class="level2">7. Null-coalescing operator in R, %||%
OK, this one isn’t in base R – yet! In the upcoming release, R will automatically provide the null-coalescing operator, %||%
. Per the release notes:
‘L %||% R’ newly in base is an expressive idiom for the ‘if(!is.null(L)) L else R’ or ‘if(is.null(L)) R else L’ phrases.
Or, in code:
`%||%` <- function(x, y) { if (is_null(x)) y else x }
Essentially, this means: if the first (left-hand) input x
is NULL
, return y
. If x
is not NULL
, return the input.
It was great to see Jenny Bryan and the R community celebrate the formal inclusion of the null-coalescing operator into the R language on Mastodon. The null-coalescing operator is particularly useful for R package developers, as highlighted by Jenny in her useR! 2018 keynote, used when the tidyverse team needs to assess whether an argument has been supplied, or if the default value which is commonly NULL
has been passed, meaning that the default argument has been supplied.
However, the null-coalescing operator can also be useful in interactive use, for functions that take NULL
as a valid argument. In this case, if supplied in the argument itself it can yield different interesting behaviors. For example:
There’s more discussion about the utility of the function.
< section id="the-fun-ctions-never-stop" class="level2">The fun-ctions never stop
Want even more functions (base R or not)? Here are some other resources to check out:
- Maëlle Salmon’s blog posts on useful functions
- Neil Wright’s post on five useful R functions
- Yihui Xie’s list of three useful functions in base R
- Ella Kaye’s Advent of Code walkthroughs
- Ihaddaden M. EL Fodil, Ph.D’s Twitter thread
- TidyX Screencasts, such as this one
Thanks to all community members sharing their code and functions!
Footnotes
Many thanks to the following resources for making this post possible:
- George Stagg’s webR and the webR documentation.
- James Joseph Balamuta’s Quarto extension for webR.
- Brian Kent’s blog post on adding headers to a Quarto blog on Netlify.
This is a handy guide for seeing the packages loaded in your R session!↩︎
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.