Skip to content

Commit 67f2874

Browse files
committed
add type conversion support to GForce
1 parent a8dde19 commit 67f2874

File tree

2 files changed

+17
-5
lines changed

2 files changed

+17
-5
lines changed

R/data.table.R

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,9 @@ replace_dot_alias = function(e) {
378378
}
379379
}
380380
# Pattern 3b: Map(fun, .SD)
381-
else if (is.call(jsub) && jsub %iscall% "Map" && length(jsub) >= 3L && jsub[[3L]] == ".SD" && length(sdvars)) {
381+
# Only optimize if .SD appears exactly once to avoid cases like Map(rep, .SD, .SD)
382+
else if (is.call(jsub) && jsub %iscall% "Map" && length(jsub) >= 3L && jsub[[3L]] == ".SD" && length(sdvars) &&
383+
sum(vapply_1b(as.list(jsub), function(x) identical(x, quote(.SD)))) == 1L) {
382384
massage_result = .massageSD(jsub, sdvars, SDenv, funi)
383385
jsub = massage_result$jsub
384386
jvnames = massage_result$jvnames
@@ -3313,13 +3315,15 @@ is_constantish = function(q, check_singleton=FALSE) {
33133315
.gweighted.mean_ok = function(q, x) { #3977
33143316
q = match.call(gweighted.mean, q)
33153317
is_constantish(q[["na.rm"]]) &&
3318+
!(is.symbol(q[["na.rm"]]) && q[["na.rm"]] %chin% names(x)) &&
33163319
(is.null(q[["w"]]) || eval(call('is.numeric', q[["w"]]), envir=x))
33173320
}
33183321
# run GForce for simple f(x) calls and f(x, na.rm = TRUE)-like calls where x is a column of .SD
33193322
.get_gcall = function(q) {
33203323
if (!is.call(q)) return(NULL)
33213324
# is.symbol() is for #1369, #1974 and #2949
3322-
if (!is.symbol(q[[2L]])) return(NULL)
3325+
if (!is.symbol(q[[2L]]) && !is.call(q[[2L]])) return(NULL)
3326+
if (is.call(q[[2L]]) && !.is_type_conversion(q[[2L]])) return(NULL)
33233327
q1 = q[[1L]]
33243328
if (is.symbol(q1)) return(if (q1 %chin% gfuns) q1)
33253329
if (!q1 %iscall% "::") return(NULL)
@@ -3332,12 +3336,20 @@ is_constantish = function(q, check_singleton=FALSE) {
33323336
# is robust to unnamed expr. Note that NA names are not possible here.
33333337
.arg_is_narm = function(expr, which=3L) !is.null(nm <- names(expr)[which]) && startsWith(nm, "na")
33343338

3339+
.is_type_conversion = function(expr) {
3340+
is.call(expr) && is.symbol(expr[[1L]]) && expr[[1L]] %chin%
3341+
c("as.numeric", "as.double", "as.integer", "as.character", "as.integer64",
3342+
"as.complex", "as.logical", "as.Date", "as.POSIXct", "as.factor")
3343+
}
3344+
33353345
.gforce_ok = function(q, x, envir=parent.frame(2L)) {
33363346
if (is.N(q)) return(TRUE) # For #334
33373347
q1 = .get_gcall(q)
33383348
if (is.null(q1)) return(FALSE)
3339-
if (!(q2 <- q[[2L]]) %chin% names(x) && q2 != ".I") return(FALSE) # 875
3340-
if (length(q)==2L || (.arg_is_narm(q) && is_constantish(q[[3L]]))) return(TRUE)
3349+
q2 = if (.is_type_conversion(q[[2L]]) && is.symbol(q[[2L]][[2L]])) q[[2L]][[2L]] else q[[2L]]
3350+
if (!q2 %chin% names(x) && q2 != ".I") return(FALSE) # 875
3351+
if (length(q)==2L || (.arg_is_narm(q) && is_constantish(q[[3L]]) &&
3352+
!(is.symbol(q[[3L]]) && q[[3L]] %chin% names(x)))) return(TRUE)
33413353
switch(as.character(q1),
33423354
"shift" = .gshift_ok(q),
33433355
"weighted.mean" = .gweighted.mean_ok(q, x),

src/gsumm.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,7 @@ SEXP gsum(SEXP x, SEXP narmArg)
410410
//Rprintf(_("gsum int took %.3f\n"), wallclock()-started);
411411
if (overflow) {
412412
UNPROTECT(1); // discard the result with overflow
413-
warning(_("The sum of an integer column for a group was more than type 'integer' can hold so the result has been coerced to 'numeric' automatically for convenience."));
413+
warning(_("The sum of an integer column for a group was more than type 'integer' can hold so the result has been coerced to 'numeric' automatically for convenience. Consider using 'as.numeric' on the column beforehand to avoid this warning."));
414414
ans = PROTECT(allocVector(REALSXP, ngrp));
415415
double *restrict ansp = REAL(ans);
416416
memset(ansp, 0, ngrp*sizeof(double));

0 commit comments

Comments
 (0)