library(tidyverse)
library(testthat)
Use base::dput()
to easily create and save objects
Background
Lately, I’ve been doing a lot of data validation tests for a package I’m working on. Using testthat
for the testing framework, some of the tests I’m writing verify dataset column names. For instance, these tests tend to look something like this:
test_that("column names are as expected", {
expect_named(
mtcars, c("mpg", "cyl", "disp", "hp", "drat", "wt", "qsec", "vs", "am", "gear", "carb")
) })
Test passed 🥇
Since mtcars
only has 11 columns, the character vector used for the column name test is pretty small. Creating this by hand isn’t too bad. However, what if we need to create a character vector for a dataset much larger than this. Say a dataset with 150+ columns–soul crushing. I don’t know about you, but I would hate to hand key a character vector this long (I’m sad to report I’ve done this more times than I would like to admit). Of course, there’s a better way. Use base::dput()
.
TIL: Use dput()
According to the docs, dput
:
Writes an ASCII text representation of an R object to a file, the R console, or a connection, or uses one to recreate the object.
Now that we have a tool to make this easier, all we need to do is pass the data to names()
, and then wrap dput()
around the return value of names()
. What results is a character vector that gets printed to the console. All we need to do now is copy and paste this output into our file. This is what this looks like:
dput(names(mtcars))
c("mpg", "cyl", "disp", "hp", "drat", "wt", "qsec", "vs", "am",
"gear", "carb")
Pretty neat.
dput()
also has a file argument, so you can pass along a file string the object will be written. Since I tend to save multiple objects in one file from time to time in a tests fixtures file, I rarely output to a file. Here’s the code to output the object to a file if your interested, though:
dput(
names(mtcars),
::here("til/posts/2024-02-10-til-r-dput-store-objects/mtcars-names.R")
here )
One more tip, if you use vim or nvim
I’m particular with how I style long character vectors within a file. If the objects can’t fit on one line, each will be placed on their own line. So you can output your object and use the following substitution command to place each object on it’s own line.
:.,+1s/, /,\r/g
This command will make our object look like this:
Indeed, it’s not perfect, but it’s close. We only needed to make some minor edits to finish it. But in the end, we’ve saved so much time, and we have a well formatted character vector.
Wrap up
I wish I came across dput()
much earlier. Not only is it one of those entire workflow changing tips, it’s one that would have saved me so much time. Hopefully if you’re reading this post, you avoid hand creating large character vectors and just use base::dput()
.
Reuse
Citation
@misc{berke2024,
author = {Berke, Collin K},
title = {Use `Base::dput()` to Easily Create and Save Objects},
date = {2024-02-10},
langid = {en}
}