4

~2 GB (525600 行 x 302 列) の 120 個のファイルのコレクションで作業する必要があります。目標は、いくつかの統計を作成し、結果をクリーンな SQLite データベースに入れることです。

read.table() を使用してスクリプトをインポートすると、すべて正常に動作しますが、遅いです。そのため、data.table パッケージ (バージョン 1.9.2) の fread を試してみましたが、次のエラーが表示されます。

Error in fread(txt, header = T, select = c("YYY", "MM", "DD",  : 
Not positioned correctly after testing format of header row. ch=' '

データの最初の 2 行と 7 行は次のようになります。

 YYYY MM DD HH mm             19490             40790
 1991 10  1  1  0      1.046465E+00      1.568405E+00

したがって、先頭に最初のスペースがあり、次に日付列の間に 1 つのスペースだけがあり、次に他の列の間に任意の数のスペースがあります。

次のようなコマンドを使用して、スペースをコンマに変換しようとしました:

DT <- fread(
            paste("sed 's/\\s\\+/,/g'", txt),
            header=T,
            select=c('HHHH','MM','DD','HH')
)

成功せず : 問題は残り、sed コマンドでは遅いようです。

Fread は、「任意の数のスペース」をセパレーターとして使用したり、先頭に空の列を配置したりするのが好きではないようです。何か案が ?

これは(おそらく)最小の再現可能な例です(40790の後の改行文字):

txt<-print(" YYYY MM DD HH mm             19490             40790
 1991 10  1  1  0      1.046465E+00      1.568405E+00")

testDT<-fread(txt,
              header=T,
              select=c("YYY","MM","DD","HH")
)

ご協力いただきありがとうございます !

更新: - data.table 1.8.* ではエラーは発生しません。このバージョンでは、テーブルは 1 つの一意の行として読み取られますが、これは良くありません。

更新 2 - コメントで述べたように、sed を使用してテーブルをフォーマットし、fread で読み取ることができました。上記の回答にスクリプトを入れて、サンプル データセットを作成し、次に system.time () を比較します。

4

5 に答える 5

5

v1.9.5の開発に専念しました。デフォルトで引数をfread()取得します(より望ましいため、 とは対照的に)。サンプル データがテストに追加されました。strip.whiteTRUEbase::read.table()

この最近のコミットでは:

require(data.table) # v1.9.5, commit 0e7a835 or more recent
ans <- fread(" YYYY MM DD HH mm             19490             40790\n   1991 10  1  1  0      1.046465E+00      1.568405E+00")
#      V1 V2 V3 V4 V5           V6           V7
# 1: YYYY MM DD HH mm 19490.000000 40790.000000
# 2: 1991 10  1  1  0     1.046465     1.568405
sapply(ans, class)
#          V1          V2          V3          V4          V5          V6          V7 
# "character" "character" "character" "character" "character"   "numeric"   "numeric" 
于 2015-09-16T00:42:37.097 に答える
2

sedの代わりにawkを使用して、はるかに高速に実行する別の方法を見つけました。別の例を次に示します。

library(data.table)

# create path to new temporary file
origData <- tempfile(pattern="origData",fileext=".txt")

# write table with irregular blank spaces separators.
write(paste0(" YYYY MM DD HH mm             19490             40790","\n",
            paste(rep(" 1991 10  1  1  0      1.046465E+00      1.568405E+00", 5e6),
            collapse="\n"),"\n"),
            file=origData
  )


# function awkFread : first awk, then fread. Argument : colNums = selection of columns. 
awkFread<-function(file, colNums, ...){
        require(data.table)
        if(is.vector(colNums)){
            tmpPath<-tempfile(pattern='tmp',fileext='.txt')
            colGen<-paste0("$",colNums,"\",\"", collapse=",")
            colGen<-substr(colGen,1,nchar(colGen)-3)
            cmdAwk<-paste("awk '{print",colGen,"}'", file, '>', tmpPath)
            try(system(cmdAwk))
            DT<-fread(tmpPath,...)
            try(system(paste('rm', tmpPath)))
            return(DT)
        }
}

# check read time :
system.time(
            DT3 <- awkFread(origData,c(1:5),header=T)
            )

> user  system elapsed 
> 6.230   0.408   6.644
于 2014-03-10T16:18:18.413 に答える
1

ピーク メモリが問題にならない場合、または管理可能なチャンクでストリーミングできる場合は、次のgsub()/fread()ハイブリッドが機能し、すべての連続するスペース文字を選択した単一の区切り文字 (例: "\t") に変換してから、 で解析する必要がありfread()ます。

fread_blank = function(inputFile, spaceReplace = "\t", n = -1, ...){
  fread(
    input = paste0(
      gsub(pattern = "[[:space:]]+",
           replacement = spaceReplace,
           x = readLines(inputFile, n = n)),
      collapse = "\n"),
    ...)
}

スペースで区切られたファイルは理想的な選択ではないという意見には同意せざるを得ませんが、好むと好まざるとにかかわらず、かなりの頻度でスペース区切りのファイルに遭遇します。

于 2016-01-26T00:22:21.287 に答える