Is there a way for fread
to mimic the behaviour of read.table
whereby the class
of the variable is set by the data that is read in.
Ok, the customer is abusing CSV format to intentionally write out trailing string rows to an integer column, yet without those rows starting with a comment.char (#
).
Then you somehow expect you can override fread()
's type inference to read those as integer, by using nrow to try to limit it to just see the integer rows. read.csv(..., nrow)
will accept this, however fread()
always uses all rows for type-inference (not just the ones specified by nrow, skip, header
), and even if they start with comment.char (that's a bug).
#
fread()
needs a fix/enhance to ignore comment rows for type inference.fread()
by post-processing the data-table read in.fread()
should be changed to support the behavior you want: using nrows to limit what gets exposed to type-inference. It might fix your (pretty unique) case and break some others.I don't see why you (EDIT: the customer) can't write your comments to a separate .txt
/README/data-dictionary file to accompany the .csv
. The practice of using a separate data-dictionary file is pretty well-established.
I've never seen someone do this to a CSV file. At least move the comments to the header, not a footer.
Option 1: Using a system command
fread()
allows the use of a system command in its first argument. We can use it to remove the quotes in the first column of the file.
indt <- data.table::fread("cat test.csv | tr -d '\"'", nrows = 100)
str(indt)
# Classes ‘data.table’ and 'data.frame': 100 obs. of 2 variables:
# $ x: int 1 2 3 4 5 6 7 8 9 10 ...
# $ y: int 1 2 3 4 5 6 7 8 9 10 ...
# - attr(*, ".internal.selfref")=<externalptr>
The system command cat test.csv | tr -d '\"'
explained:
cat test.csv
reads the file to standard output|
is a pipe, using the output of the previous command as input for the next command tr -d '\"'
deletes (-d
) all occurrences of double quotes ('\"'
) from the current inputOption 2: Coercion after reading
Since option 1 doesn't seem to be working on your system, another possibility is to read the file as you did, but convert the x
column with type.convert()
.
library(data.table)
indt2 <- fread("test.csv", nrows = 100)[, x := type.convert(x)]
str(indt2)
# Classes ‘data.table’ and 'data.frame': 100 obs. of 2 variables:
# $ x: int 1 2 3 4 5 6 7 8 9 10 ...
# $ y: int 1 2 3 4 5 6 7 8 9 10 ...
# - attr(*, ".internal.selfref")=<externalptr>
Side note: I usually prefer to use type.convert()
over as.numeric()
to avoid the "NAs introduced by coercion" warning triggered in some cases. For example,
x <- c("1", "4", "NA", "6")
as.numeric(x)
# [1] 1 4 NA 6
# Warning message:
# NAs introduced by coercion
type.convert(x)
# [1] 1 4 NA 6
But of course you can use as.numeric()
as well.
Note: This answer assumes data.table dev v1.9.5