Skip to content

Commit 6719e11

Browse files
committed
add catering for header
1 parent 5702176 commit 6719e11

File tree

2 files changed

+21
-4
lines changed

2 files changed

+21
-4
lines changed

NEWS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,8 @@ See [#2611](https://github.com/Rdatatable/data.table/issues/2611) for details. T
354354

355355
27. `dogroups()` no longer reads beyond the resized end of over-allocated data.table list columns, [#7486](https://github.com/Rdatatable/data.table/issues/7486). While this didn't crash in practice, it is now explicitly checked for in recent R versions (r89198+). Thanks @TimTaylor and @aitap for the report and @aitap for the fix.
356356

357+
28. `fread()` with `col.names=` now correctly applies `drop=` and `select=` using user-provided column names instead of auto-generated names, [#3459](https://github.com/Rdatatable/data.table/issues/3459). Thanks to @malcook for the report and @ben-schwen for the fix.
358+
357359
### NOTES
358360

359361
1. The following in-progress deprecations have proceeded:

src/freadR.c

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,8 @@ bool userOverride(int8_t *type, lenOff *colNames, const char *anchor, const int
281281
}
282282
}
283283
// "use either select= or drop= but not both" was checked earlier in freadR
284-
SEXP matchNames = isNull(cNamesSxp) ? colNamesSxp : cNamesSxp;
284+
bool hasHeader = ncol > 0 && strcmp(CHAR(STRING_ELT(colNamesSxp, 0)), "V1") != 0;
285+
SEXP matchNames = (isNull(cNamesSxp) || hasHeader) ? colNamesSxp : cNamesSxp;
285286
applyDrop(dropSxp, type, ncol, /*dropSource=*/-1, matchNames);
286287
if (TYPEOF(colClassesSxp) == VECSXP) { // not isNewList() because that returns true for NULL
287288
SEXP listNames = PROTECT(getAttrib(colClassesSxp, R_NamesSymbol)); // rchk wanted this protected
@@ -326,9 +327,23 @@ bool userOverride(int8_t *type, lenOff *colNames, const char *anchor, const int
326327
// override col names if user provided them
327328
if (!isNull(cNamesSxp)) {
328329
int ncnames = LENGTH(cNamesSxp);
329-
if (ncnames != ncol) STOP(_("Can't assign %d names to a %d-column data.table"), ncnames, ncol);
330-
for (int i = 0; i < ncol; i++) {
331-
SET_STRING_ELT(colNamesSxp, i, STRING_ELT(cNamesSxp, i));
330+
if (hasHeader) {
331+
int ndrop = 0;
332+
for (int i = 0; i < ncol; i++) if (type[i] == CT_DROP) ndrop++;
333+
if (ncnames != (ncol - ndrop)) STOP(_("Can't assign %d names to a %d-column data.table"), ncnames, ncol - ndrop);
334+
int *selectRankD = selectRank ? INTEGER(selectRank) : NULL;
335+
int cname_idx = 0;
336+
for (int i = 0; i < ncol; i++) {
337+
if (type[i] != CT_DROP) {
338+
const int idx = selectRankD ? (selectRankD[i] - 1) : cname_idx++;
339+
SET_STRING_ELT(colNamesSxp, i, STRING_ELT(cNamesSxp, idx));
340+
}
341+
}
342+
} else {
343+
if (ncnames != ncol) STOP(_("Can't assign %d names to a %d-column data.table"), ncnames, ncol);
344+
for (int i = 0; i < ncol; i++) {
345+
SET_STRING_ELT(colNamesSxp, i, STRING_ELT(cNamesSxp, i));
346+
}
332347
}
333348
}
334349
colClassesAs = NULL; // any coercions we can't handle here in C are deferred to R (to handle with methods::as) via this attribute

0 commit comments

Comments
 (0)