Data.table: glue() doesn't work with data.table

Created on 21 Jan 2021  路  5Comments  路  Source: Rdatatable/data.table

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

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() 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

All 5 comments

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

Was this page helpful?
0 / 5 - 0 ratings