16 {glue}
Note
This lecture used materials from the {glue} package vignette.
The glue package contains functions for string interpolation: gluing together character strings and R code.
Gluing and interpolating
-
glue()
can be used to glue together pieces of text:
glue("glue", "some", "text", "together")
## gluesometexttogether
glue("glue", "some", "text", "together", .sep=" " )
## glue some text together
- But glue’s real power comes with
{}
: anything inside of{}
is evaluated and pasted into the string. This makes it easy to interpolate variables:
name <- "glue"
glue("We are learning how to use the {name} R package.")
## We are learning how to use the glue R package.
- As well as more complex expressions:
## Release was on a Tuesday.
What you see is awfully close to what you get
-
glue()
lets you write code that makes it easy to predict what the final string will look like. There is considerably less syntactical noise and mystery compared topaste()
andsprintf()
.
glue("
A formatted string
Can have multiple lines
with additional indention preserved
"
)
## A formatted string
## Can have multiple lines
## with additional indention preserved
- You can break the texts into individual pieces if you want (e.g. to limit the length of lines in your source code to, e.g., 80 characters), and the results do not change.
glue("The first version of the glue package was released on a {format(release_date, '%A')}.")
## The first version of the glue package was released on a Tuesday.
glue("The first version of the glue package was released on ",
"a {format(release_date, '%A')}.")
## The first version of the glue package was released on a Tuesday.
Delimiters
- By default, code to be evaluated goes inside
{}
in a glue string. If want a literal curly brace in your string, double it:
glue("The name of the package is {name}, not {{name}}.")
## The name of the package is glue, not {name}.
- If you don’t want to use
{}
? No problem! You can customize the delimiters using.open
and.close
.
glue("The name of the package is [name], not {name}.",
.open = "[", .close = "]")
## The name of the package is glue, not {name}.
Where glue looks for values
- By default,
glue()
evaluates in the global environment.
x <- "the caller environment"
glue("By default, `glue()` evaluates code in {x}.")
## By default, `glue()` evaluates code in the caller environment.
- But you can provide more narrowly scoped values by passing them in
name = value
form:
x <- "the local environment"
glue(
"`glue()` can access values from {x} or from {y}. {z}",
y = "named arguments",
z = "Woo!"
)
## `glue()` can access values from the local environment or from named arguments. Woo!
- If the relevant data lives in a data frame (or list or environment), use
glue_data()
instead:
mini_mtcars <- head(cbind(model = rownames(mtcars), mtcars))
rownames(mini_mtcars) <- NULL
glue_data(mini_mtcars, "{model} has {hp} hp.")
## Mazda RX4 has 110 hp.
## Mazda RX4 Wag has 110 hp.
## Datsun 710 has 93 hp.
## Hornet 4 Drive has 110 hp.
## Hornet Sportabout has 175 hp.
## Valiant has 105 hp.
-
glue_data()
is very natural to use with the pipe:
mini_mtcars |>
glue_data("{model} gets {mpg} miles per gallon.")
## Mazda RX4 gets 21 miles per gallon.
## Mazda RX4 Wag gets 21 miles per gallon.
## Datsun 710 gets 22.8 miles per gallon.
## Hornet 4 Drive gets 21.4 miles per gallon.
## Hornet Sportabout gets 18.7 miles per gallon.
## Valiant gets 18.1 miles per gallon.
- Returning to
glue()
, recall that it defaults to evaluation in the caller environment. This has happy implications inside adplyr::mutate()
pipeline. The data-masking feature ofmutate()
means the columns of the target data frame are “in scope” for aglue()
call:
library(dplyr)
mini_mtcars |>
mutate(note = glue("{model} gets {mpg} miles per gallon.")) |>
select(note, cyl, disp)
## note cyl disp
## 1 Mazda RX4 gets 21 miles per gallon. 6 160
## 2 Mazda RX4 Wag gets 21 miles per gallon. 6 160
## 3 Datsun 710 gets 22.8 miles per gallon. 4 108
## 4 Hornet 4 Drive gets 21.4 miles per gallon. 6 258
## 5 Hornet Sportabout gets 18.7 miles per gallon. 8 360
## 6 Valiant gets 18.1 miles per gallon. 6 225
Why glue
- You might have seen
paste()
paste("file_", 1:5, ".csv", sep = "")
## [1] "file_1.csv" "file_2.csv" "file_3.csv" "file_4.csv" "file_5.csv"
- Or
paste0()
, where you don’t no need to writesep = ""
all the time
paste0("file_", 1:5, ".csv")
## [1] "file_1.csv" "file_2.csv" "file_3.csv" "file_4.csv" "file_5.csv"
- Or
sprintf()
sprintf("file_%s.csv", 1:5)
## [1] "file_1.csv" "file_2.csv" "file_3.csv" "file_4.csv" "file_5.csv"
-
glue
beats them all:
glue("file_{1:5}.csv")
## file_1.csv
## file_2.csv
## file_3.csv
## file_4.csv
## file_5.csv
glue("Pi is {round(pi, 1:4)}")
## Pi is 3.1
## Pi is 3.14
## Pi is 3.142
## Pi is 3.1416
glue("I got {41:45} in AST-{201:205}")
## I got 41 in AST-201
## I got 42 in AST-202
## I got 43 in AST-203
## I got 44 in AST-204
## I got 45 in AST-205
Summary:
Two main functions: glue()
and glue_data()
does almost all the jobs