Skip to content

Commit edaf377

Browse files
specify use of quote and substitute with example
1 parent 4407f1c commit edaf377

File tree

2 files changed

+16
-5
lines changed

2 files changed

+16
-5
lines changed

NEWS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
+ Argument `in.place` to `droplevels` has been removed.
2828
+ It's now an error to set `datatable.nomatch`, which has been warning since 1.15.0.
2929

30-
3. The groupingsets() documentation now explicitly addresses scoping issues when using variables from outer environments (e.g., function parameters) in aggregation expressions. Previously, using such variables in j could lead to "object not found" errors due to evaluation environment mismatches. This is resolved by using jj = substitute(expr) instead, which captures both the expression and its environment per R’s scoping rules (§6). Three new examples demonstrate proper usage, including function parameter references (e.g., sum(value > threshold)) and multi-aggregation patterns.
30+
3. The groupingsets() documentation now explicitly addresses scoping issues when using variables from outer environments (e.g., function parameters) in aggregation expressions. Previously, using such variables in j could lead to "object not found" errors due to evaluation environment mismatches. This is resolved by using jj = substitute(expr) instead, which captures both the expression and its environment per R’s scoping rules (Chapter 6 of the R Language Definition manual). Three new examples demonstrate proper usage, including function parameter references (e.g., sum(value > threshold)) and multi-aggregation patterns.
3131

3232
# data.table [v1.17.0](https://github.com/Rdatatable/data.table/milestone/34) (20 Feb 2025)
3333

man/groupingsets.Rd

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ groupingsets(x, \dots)
3535

3636
The \code{label = <scalar>} option provides a shorter alternative in the case where only one class of grouping variable requires a label. For example, \code{label = list(character = "Total")} can be shortened to \code{label = "Total"}. When this option is used, the label will be applied to all variables in \code{by} for which the first element of the class of the variable in \code{x} matches the first element of the class of the scalar.
3737

38-
The \code{jj} argument provides a mechanism to handle scoping issues when working with variables from outer environments. When using \code{j} directly with variables not defined in the columns of the data.table, R's evaluation rules may not find these variables, resulting in "object not found" errors. The \code{jj} argument accepts a quoted expression created with \code{substitute()}, which captures both the expression and its environment. This approach is particularly useful in functions where parameters need to be referenced within aggregation expressions. When \code{jj} is provided, the function will ignore any value specified in the \code{j} argument.
38+
The \code{jj} argument provides a mechanism to handle scoping issues when working with variables from outer environments. When using \code{j} directly with variables not defined in the columns of the data.table, R's evaluation rules may not find these variables, resulting in "object not found" errors. The \code{jj} argument accepts a quoted expression which can be created with either \code{quote()} (for direct calls referencing only columns and special symbols) or \code{substitute()} (when inside functions that need to capture parameters from the outer environment). This approach is particularly useful in functions where parameters need to be referenced within aggregation expressions. When \code{jj} is provided, the function will ignore any value specified in the \code{j} argument.
3939
}
4040
\value{
4141
A data.table with various aggregates.
@@ -83,15 +83,26 @@ cube(DT, j = c(list(count=.N), lapply(.SD, sum)), by = c("color","year","status"
8383
# groupingsets
8484
groupingsets(DT, j = c(list(count=.N), lapply(.SD, sum)), by = c("color","year","status"),
8585
sets = list("color", c("year","status"), character()), id=TRUE)
86+
8687
# Using jj argument(enables access to variables from outer environments)
87-
groupingsets(DT, jj = substitute(c(list(count=.N), lapply(.SD, sum))),
88+
groupingsets(DT, jj = quote(c(list(count=.N), lapply(.SD, sum))),
8889
by = c("color","year","status"), # Basic jj usage with substitute()
8990
sets = list("color", c("year","status"), character()), id = TRUE, .SDcols = "value")
90-
groupingsets(DT, jj = substitute(lapply(.SD, sum)),
91+
groupingsets(DT, jj = quote(lapply(.SD, sum)),
9192
by = c("color","year","status"), # Simple aggregation with jj
9293
sets = list("color", c("year","status"), character()), id = TRUE, .SDcols = "value")
93-
groupingsets(DT, jj = substitute(list(count = .N, total = sum(value))),
94+
groupingsets(DT, jj = quote(list(count = .N, total = sum(value))),
9495
by = c("color","year","status"), # jj with direct column references
9596
sets = list("color", c("year","status"), character()), id = TRUE)
97+
98+
# Example showing when substitute() is necessary - in a wrapper function
99+
custom_grouping <- function(dt, multiplier = 1) {
100+
# Here substitute() is needed to capture 'multiplier' from function environment
101+
groupingsets(dt, jj = substitute(list(count = .N, total = sum(value) * multiplier)),
102+
by = c("color", "year", "status"),sets = list("color", c("year", "status"), character()),
103+
id = TRUE)
104+
}
105+
# Using the wrapper function
106+
custom_grouping(DT, multiplier = 2)
96107
}
97108
\keyword{ data }

0 commit comments

Comments
 (0)