Skip to content

Commit

Permalink
Closes #1740. Subassigning a factor column by reference with NA/logic…
Browse files Browse the repository at this point in the history
…al type work as expected.
  • Loading branch information
arunsrinivasan committed Aug 11, 2016
1 parent cca52d5 commit 29da81e
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 4 deletions.
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,8 @@

71. `rbind` for data.tables now coerces non-list inputs to data.tables first before calling `rbindlist` so that binding list of data.tables and matrices work as expected to be consistent with base's rbind, [#1626](https://github.com/Rdatatable/data.table/issues/1626). Thanks @ems for reporting [here](http://stackoverflow.com/q/34426957/559784) on SO.

72. Subassigning a factor column with `NA` works as expected. Also, the warning message on coercion is suppressed when RHS is singleton NA, [#1740](https://github.com/Rdatatable/data.table/issues/1740). Thanks @Zus.

#### NOTES

1. Updated error message on invalid joins to reflect the new `on=` syntax, [#1368](https://github.com/Rdatatable/data.table/issues/1368). Thanks @MichaelChirico.
Expand Down
5 changes: 5 additions & 0 deletions inst/tests/tests.Rraw
Original file line number Diff line number Diff line change
Expand Up @@ -9123,6 +9123,11 @@ test(1693.7, month(t), 8L)
test(1693.8, quarter(t), 3L)
test(1693.9, year(t), 2016L)

# fix for #1740 - sub-assigning NAs for factors
dt = data.table(x = 1:5, y = factor(c("","a","b","a", "")), z = 5:9)
ans = data.table(x = 1:5, y = factor(c(NA,"a","b","a", NA)), z = 5:9)
test(1694.0, dt[y=="", y := NA], ans)

##########################

# TODO: Tests involving GForce functions needs to be run with optimisation level 1 and 2, so that both functions are tested all the time.
Expand Down
9 changes: 5 additions & 4 deletions src/assign.c
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,7 @@ SEXP assign(SEXP dt, SEXP rows, SEXP cols, SEXP newcolnames, SEXP values, SEXP v
if (isMatrix(thisvalue) && (j=INTEGER(getAttrib(thisvalue, R_DimSymbol))[1]) > 1) // matrix passes above (considered atomic vector)
warning("%d column matrix RHS of := will be treated as one vector", j);
if ((coln+1)<=oldncol && isFactor(VECTOR_ELT(dt,coln)) &&
!isString(thisvalue) && TYPEOF(thisvalue)!=INTSXP && !isReal(thisvalue) && !isNewList(thisvalue)) // !=INTSXP includes factor
!isString(thisvalue) && TYPEOF(thisvalue)!=INTSXP && TYPEOF(thisvalue)!=LGLSXP && !isReal(thisvalue) && !isNewList(thisvalue)) // !=INTSXP includes factor
error("Can't assign to column '%s' (type 'factor') a value of type '%s' (not character, factor, integer or numeric)", CHAR(STRING_ELT(names,coln)),type2char(TYPEOF(thisvalue)));
if (nrow>0) {
if (vlen>targetlen)
Expand Down Expand Up @@ -560,12 +560,13 @@ SEXP assign(SEXP dt, SEXP rows, SEXP cols, SEXP newcolnames, SEXP values, SEXP v
savetl_end();
} else {
// value is either integer or numeric vector
if (TYPEOF(thisvalue)!=INTSXP && !isReal(thisvalue))
if (TYPEOF(thisvalue)!=INTSXP && TYPEOF(thisvalue)!=LGLSXP && !isReal(thisvalue))
error("Internal logical error. Up front checks (before starting to modify DT) didn't catch type of RHS ('%s') assigning to factor column '%s'. Please report to datatable-help.", type2char(TYPEOF(thisvalue)), CHAR(STRING_ELT(names,coln)));
if (isReal(thisvalue)) {
if (isReal(thisvalue) || TYPEOF(thisvalue)==LGLSXP) {
PROTECT(RHS = coerceVector(thisvalue,INTSXP));
protecti++;
warning("Coerced 'double' RHS to 'integer' to match the factor column's underlying type. Character columns are now recommended (can be in keys), or coerce RHS to integer or character first.");
// silence warning on singleton NAs
if (INTEGER(RHS)[0] != NA_INTEGER) warning("Coerced '%s' RHS to 'integer' to match the factor column's underlying type. Character columns are now recommended (can be in keys), or coerce RHS to integer or character first.", type2char(TYPEOF(thisvalue)));
} else RHS = thisvalue;
for (j=0; j<length(RHS); j++) {
if ( (INTEGER(RHS)[j]<1 || INTEGER(RHS)[j]>LENGTH(targetlevels))
Expand Down

0 comments on commit 29da81e

Please sign in to comment.