Skip to content

Commit

Permalink
rbindlist works for expression column (#3811)
Browse files Browse the repository at this point in the history
  • Loading branch information
MichaelChirico authored and mattdowle committed Dec 20, 2019
1 parent fff97ff commit 00c2c67
Show file tree
Hide file tree
Showing 4 changed files with 16 additions and 7 deletions.
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ unit = "s")

8. Compiler support for OpenMP is now detected during installation, which allows data.table to compile from source (in single threaded mode) on macOS which, frustratingly, does not include OpenMP support by default, [#2161](https://github.com/Rdatatable/data.table/issues/2161), unlike Windows and Linux. A helpful message is emitted during installation from source, and on package startup as before. Many thanks to @jimhester for the PR. This was typically a problem just after release to CRAN in the few days before macOS binaries (which do support OpenMP) are made available by CRAN.

9. `rbindlist` now supports columns of type `expression`, [#546](https://github.com/Rdatatable/data.table/issues/546). Thanks @jangorecki for the report.

## BUG FIXES

1. A NULL timezone on POSIXct was interpreted by `as.IDate` and `as.ITime` as UTC rather than the session's default timezone (`tz=""`) , [#4085](https://github.com/Rdatatable/data.table/issues/4085).
Expand Down
11 changes: 8 additions & 3 deletions inst/tests/tests.Rraw
Original file line number Diff line number Diff line change
Expand Up @@ -16673,7 +16673,12 @@ test(2128.3, DT[, .SD, .SDcols=function(x) x==1], error='conditions were not met
test(2128.4, DT[, .SD, .SDcols=function(x) 2L], error='conditions were not met for: [a, b, c]')
test(2128.5, DT[, .SD, .SDcols=function(x) NA], error='conditions were not met for: [a, b, c]')

# expression columns in rbindlist, #546
A = data.table(c1 = 1, c2 = 'asd', c3 = expression(as.character(Sys.time())))
B = data.table(c1 = 3, c2 = 'qwe', c3 = expression(as.character(Sys.time()+5)))
test(2129, rbind(A,B)$c3, expression(as.character(Sys.time()), as.character(Sys.time()+5)))

###################################
# Add new tests above this line #
###################################

########################
# Add new tests here #
########################
3 changes: 2 additions & 1 deletion src/assign.c
Original file line number Diff line number Diff line change
Expand Up @@ -1061,7 +1061,8 @@ const char *memrecycle(SEXP target, SEXP where, int start, int len, SEXP source,
BODY(SEXP, STRING_PTR, SEXP, val, SET_STRING_ELT(target, off+i, cval))
}
case VECSXP :
if (TYPEOF(source)!=VECSXP)
case EXPRSXP : // #546
if (TYPEOF(source)!=VECSXP && TYPEOF(source)!=EXPRSXP)
BODY(SEXP, &, SEXP, val, SET_VECTOR_ELT(target, off+i, cval))
else
BODY(SEXP, VECTOR_PTR, SEXP, val, SET_VECTOR_ELT(target, off+i, cval))
Expand Down
7 changes: 4 additions & 3 deletions src/rbindlist.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,8 @@ SEXP rbindlist(SEXP l, SEXP usenamesArg, SEXP fillArg, SEXP idcolArg)
}
SEXP thisCol = VECTOR_ELT(li, w);
int thisType = TYPEOF(thisCol);
if (TYPEORDER(thisType)>TYPEORDER(maxType)) maxType=thisType;
// Use >= for #546 -- TYPEORDER=0 for both LGLSXP and EXPRSXP (but also NULL)
if (TYPEORDER(thisType)>=TYPEORDER(maxType) && !isNull(thisCol)) maxType=thisType;
if (isFactor(thisCol)) {
if (isNull(getAttrib(thisCol,R_LevelsSymbol))) error("Column %d of item %d has type 'factor' but has no levels; i.e. malformed.", w+1, i+1);
factor = true;
Expand Down Expand Up @@ -513,9 +514,9 @@ SEXP rbindlist(SEXP l, SEXP usenamesArg, SEXP fillArg, SEXP idcolArg)
if (w==-1 || !length(thisCol=VECTOR_ELT(li, w))) { // !length for zeroCol warning above; #1871
writeNA(target, ansloc, thisnrow); // writeNA is integer64 aware and writes INT64_MIN
} else {
if (TYPEOF(target)==VECSXP && TYPEOF(thisCol)!=VECSXP) {
if ((TYPEOF(target)==VECSXP || TYPEOF(target)==EXPRSXP) && TYPEOF(thisCol)!=TYPEOF(target)) {
// do an as.list() on the atomic column; #3528
thisCol = PROTECT(coerceVector(thisCol, VECSXP)); nprotect++;
thisCol = PROTECT(coerceVector(thisCol, TYPEOF(target))); nprotect++;
}
// else coerces if needed within memrecycle; with a no-alloc direct coerce from 1.12.4 (PR #3909)
const char *ret = memrecycle(target, R_NilValue, ansloc, thisnrow, thisCol, idcol+j+1, foundName);
Expand Down

0 comments on commit 00c2c67

Please sign in to comment.