J's blog

趣味で統計•データ解析をしています

fread(data.table 1.9.2)の引数sep2が使えない

これは本当に題意のとおりで、割とつまづいたのでメモ。

まずfread関数とは、高速にデータテーブルを読み込んでくれる
data.tableパッケージの関数のことです。
区切り文字などを指定しなくても自動で対応したり、列選択ができるなど、
高速さ以外にも便利だったのですが、問題発生です。

sep2という改行コードを操作する引数があるのですが、これをどのように変更しても
改行コードが変更されず、正しくデータが読み込めませんでした。

「sep2="\r\n"という表記が悪いのか???」

色々試しましたが、何しても変更されない上、そもそもエラーすら出ないという...
というわけで中身を拝見。

function (input = "test.csv", sep = "auto", sep2 = "auto", nrows = -1L, 
    header = "auto", na.strings = "NA", stringsAsFactors = FALSE, 
    verbose = FALSE, autostart = 30L, skip = -1L, select = NULL, 
    drop = NULL, colClasses = NULL, integer64 = getOption("datatable.integer64"), 
    showProgress = getOption("datatable.showProgress")) 
{
    if (!is.character(input) || length(input) != 1) {
        stop("'input' must be a single character string containing a file name, a command, full path to a file, a URL starting 'http://' or 'file://', or the input data itself")
    }
    else if (substring(input, 1, 7) %chin% c("http://", "https:/", 
        "file://")) {
        tt = tempfile()
        on.exit(unlink(tt), add = TRUE)
        download.file(input, tt)
        input = tt
    }
    else if (input == "" || length(grep("\\n|\\r", input)) > 
        0) {
    }
    else if (!file.exists(input)) {
        tt = tempfile()
        on.exit(unlink(tt), add = TRUE)
        if (.Platform$OS.type == "unix") {
            if (file.exists("/dev/shm") && file.info("/dev/shm")$isdir) {
                tt = tempfile(tmpdir = "/dev/shm")
            }
            system(paste("(", input, ") > ", tt, sep = ""))
        }
        else {
            shell(paste("(", input, ") > ", tt, sep = ""))
        }
        input = tt
    }
    if (identical(header, "auto")) 
        header = NA
    if (identical(sep, "auto")) 
        sep = NULL
    if (is.atomic(colClasses) && !is.null(names(colClasses))) 
        colClasses = tapply(names(colClasses), colClasses, c, 
            simplify = FALSE)
    ans = .Call(Creadfile, input, sep, as.integer(nrows), header, 
        na.strings, verbose, as.integer(autostart), skip, select, 
        drop, colClasses, integer64, as.integer(showProgress))
    nr = length(ans[[1]])
    setattr(ans, "row.names", .set_row_names(nr))
    setattr(ans, "class", c("data.table", "data.frame"))
    if (integer64 == "integer64" && !exists("print.integer64") && 
        any(sapply(ans, inherits, "integer64"))) 
        warning("Some columns have been read as type 'integer64' but package bit64 isn't loaded. Those columns will display as strange looking floating point data. There is no need to reload the data. Just require(bit64) to obtain the integer64 print method and print the data again.")
    alloc.col(ans)
}

sep2が引数にあるのに使われてない!!??

原因が判明したという点では一件落着。。
まだまだ発展途上ということなんですかね。
でもそれなら引数に入れないか、詳細をREADMEに書くくらいはしてほしいですね。


(7/29追記)

helpマニュアルをよーく見たらあった...
「The separator within columns. A list column will be returned where each cell is a vector of values. This is much faster using less working memory than strsplit afterwards or similar
techniques. For each column sep2 can be different and is the first character in the same set above [,\t |;:], other than sep, that exists inside each field outside quoted regions on line autostart. NB: sep2 is not yet implemented.」
最後に未実装って書いてあったなんて。完全に見逃してた。