Skip to content

Commit d61c836

Browse files
authored
Reset isReal test per-column to fix forder() with na.last=TRUE (#7877)
* set isReal per-column to fix na.last handling * More tests of other data types * NEWS entry
1 parent 561a869 commit d61c836

3 files changed

Lines changed: 24 additions & 1 deletion

File tree

NEWS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@
8080

8181
18. `example(local=TRUE)` where the example uses `[.data.table` works again (e.g. `example(':=', package='data.table', local=TRUE, echo=FALSE)`), [#7855](https://github.com/Rdatatable/data.table/issues/7855) re-fixing [#2972](https://github.com/Rdatatable/data.table/issues/2972). Thanks @michaelChirico for the fix.
8282

83+
19. `DT[order(double, ..., -non_double, na.last=TRUE)]`, i.e., a double/complex column (in any order) followed by a non-double column in descending order with `na.last=TRUE`, is fixed to respect `na.last` again, [#7875](https://github.com/Rdatatable/data.table/issues/7875). The problematic behavior only occurred under specific conditions on the cardinality of the non-double column.
84+
8385
### Notes
8486

8587
1. {data.table} now depends on R 3.5.0 (2018).

inst/tests/tests.Rraw

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21891,3 +21891,24 @@ DF = DF[, 'a', drop=FALSE]
2189121891
test(2382.08, subset(DT, a > 5, select="a", drop=TRUE), subset(DF, a > 5, select="a", drop=TRUE))
2189221892
test(2382.09, subset(DT, a > 10, select="a", drop=TRUE), subset(DF, a > 10, select="a", drop=TRUE))
2189321893
test(2382.10, subset(DT, a > 5, drop=TRUE), subset(DF, a > 5, drop=TRUE))
21894+
21895+
# forder() handles na.last=TRUE correctly in ordering double with >1 unique value then non-double (#7875)
21896+
DT = data.table(
21897+
d0=c(10, 10, 10, 1),
21898+
l1=c(FALSE, TRUE, NA, TRUE),
21899+
i2=c(2:3, NA, 1L),
21900+
d3=c(2, 3, NA, 1),
21901+
z4=c(2+1i, 3+1i, NA, 1+1i),
21902+
c5=c('b', 'c', NA, 'a')
21903+
)
21904+
DT_sorted = DT[c(4L, 2:1, 3L)]
21905+
test(2383.1, DT[order(d0, -l1, na.last=TRUE)], DT_sorted)
21906+
test(2383.2, DT[order(d0, -i2, na.last=TRUE)], DT_sorted)
21907+
test(2383.3, DT[order(d0, -d3, na.last=TRUE)], DT_sorted)
21908+
test(2383.4, DT[order(d0, -z4, na.last=TRUE)], DT_sorted)
21909+
test(2383.5, DT[order(d0, -c5, na.last=TRUE)], DT_sorted)
21910+
if (test_bit64) {
21911+
DT[, i64 := as.integer64(i2)]
21912+
DT_sorted[, i64 := as.integer64(i2)]
21913+
test(2383.6, DT[order(d0, -i64, na.last=TRUE)], DT_sorted)
21914+
}

src/forder.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -562,7 +562,6 @@ SEXP forder(SEXP DT, SEXP by, SEXP retGrpArg, SEXP retStatsArg, SEXP sortGroupsA
562562
STOP(_("Unable to allocate %"PRIu64" bytes of working memory"), (uint64_t)keyAlloc*sizeof(*key)); // # nocov
563563
nradix=0; // the current byte we're writing this column to; might be squashing into it (spare>0)
564564
int spare=0; // the amount of bits remaining on the right of the current nradix byte
565-
bool isReal=false;
566565
bool complexRerun = false; // see comments below in CPLXSXP case
567566
SEXP CplxPart = R_NilValue;
568567
if (n_cplx) { CplxPart=PROTECT(allocVector(REALSXP, nrow)); n_protect++; } // one alloc is reused for each part
@@ -581,6 +580,7 @@ SEXP forder(SEXP DT, SEXP by, SEXP retGrpArg, SEXP retStatsArg, SEXP sortGroupsA
581580
}
582581
//Rprintf(_("sortType = %d\n"), sortType);
583582
hashtab * marks = NULL; // only used for STRSXP below
583+
bool isReal=false;
584584
switch(TYPEOF(x)) {
585585
case INTSXP : case LGLSXP : // TODO skip LGL and assume range [0,1]
586586
range_i32(INTEGER(x), nrow, &min, &max, &na_count);

0 commit comments

Comments
 (0)