I'm not sure if this is a {data.table} issue or a {glue} issue.
Basically glue() doesn't work inside of a {data.table} [ ] call unless you use a workaround:
library(data.table)
library(glue)
library(dplyr)
test_df <- data.table(a = letters[1:3], b = letters[1:3])
# Works with dplyr
mutate(test_df, new = glue("{a}_{b}"))
#> a b new
#> 1: a a a_a
#> 2: b b b_b
#> 3: c c c_c
# Fails with data.table
copy(test_df)[, new := glue("{a}_{b}")][]
#> Error in eval(parse(text = text, keep.source = FALSE), envir): object 'a' not found
# Workaround for data.table using `.SD` as the evaluation environment
copy(test_df)[, new := glue("{a}_{b}", .envir = .SD)][]
#> a b new
#> 1: a a a_a
#> 2: b b b_b
#> 3: c c c_c
tidyverse/glue#211
my _guess_ is that this is a glue issue, and that glue has some logic for detecting it's inside a tibble & applying the right env. not sure if there's anything we can do besides confirm the workaround feels canonical for data.table
Does glue work in base R subset or with? Broadly speaking, those are the interfaces that data.table is aiming to mimic in [.
glue has no extra logic for tibbles, it just evaluates the code within the braces in the parent.frame() of the glue call. dplyr evaluates its code within an environment chain where this just works.
It does also work with subset() and with().
with(mtcars[1:5, ], glue::glue("{hp}"))
#> 110
#> 110
#> 93
#> 110
#> 175
subset(mtcars, glue::glue("{cyl}_{gear}") == "6_3")
#> mpg cyl disp hp drat wt qsec vs am gear carb
#> Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
#> Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1
A workaround that I have used is glue_data():
IR <- data.table(iris)
IR[1, glue_data(.SD, 'It is a {Species} with Sepal.Length {Sepal.Length}')]
# It is a setosa with Sepal.Length 5.1
@sindribaldur that is the way I would recommend
Most helpful comment
glue has no extra logic for tibbles, it just evaluates the code within the braces in the
parent.frame()of the glue call. dplyr evaluates its code within an environment chain where this just works.It does also work with
subset()andwith().