web-dev-qa-db-ja.com

data.tableでapplyを実行するにはどうすればよいですか?

スペースのある文字列として、列2から20までの_data.table_があります(「種名」など)。これらすべての列でstr_replace()を同時に実行して、すべての「種名」が「種名」になるようにしたい。私はどちらかを行うことができます:

_data.table(apply(as.data.frame(dt[,2:dim(dt)[2], with=F]), 2, 
                               function(x){ str_replace(x," ","_") }))
_

または、それを_data.table_オブジェクトとして保持する場合、一度に1列ずつ行うことができます。

_dt[,SpeciesName := str_replace(SpeciesName, " ", "_")
_

上記と同様に、2から最後までのすべての列でこれを行うにはどうすればよいですか?

33
Maiasaura

以前のバージョンのエラーを修正するために2015-11-24で完全に書き直されました。

いくつかのオプションがあります。

  1. _:=_を使用してlapply()への埋め込み呼び出しですべてのターゲット列を処理し、変更された値を適切に割り当てます。これは、LHSで指定された複数の列への同時割り当てに対する_:=_の非常に便利なサポートに依存しています。

  2. forループを使用してターゲット列を1つずつ実行し、set()を使用して各列の値を順番に変更します。

  3. forループを使用して、[.data.table()への複数の「単純な」呼び出しを反復し、それぞれが単一の列を変更します。

これらの方法はすべて同じくらい高速に見えるので、どちらを使用するかは主に好みの問題になります。 (1)コンパクトで表現力豊かです。 (2)読みやすいと思うかもしれませんが、これが私が最も頻繁に使用するものです。列を一度に1つずつ処理して変更するため、(2)または(3)は、data.tableが非常に大きく、Rによって課された制限に直面する危険があるというまれな状況で有利になります。セッションの使用可能なメモリ。

_library(data.table)

## Create three identical 1000000-by-20 data.tables
DT1 <- data.table(1:1e6,
           as.data.table(replicate(1e6, paste(sample(letters, nr, TRUE),
                                             sample(letters, nr, TRUE)))))
cnames <- c("ID", paste0("X", 1:19))
setnames(DT1, cnames)
DT2 <- copy(DT1); DT3 <- copy(DT1)

## Method 1
system.time({
DT1[, cnames[-1] := lapply(DT1[,cnames[-1],with=FALSE],
                      function(x) gsub(" ", "_", x))]
})
##   user  system elapsed 
##  10.90    0.11   11.06 

## Method 2
system.time({
    for(cname in cnames[-1]) {
        set(DT2, j=cname, value=gsub(" ", "_", DT2[[cname]]))
    }
})
##   user  system elapsed 
##  10.65    0.05   10.70 

## Method 3
system.time({
    for(cname in cnames[-1]) {
        DT3[ , cname := gsub(" ", "_", DT3[[cname]]), with=FALSE]
    }
})
##   user  system elapsed 
##  10.33    0.03   10.37 
_

set()と_:=_の詳細については、_?set_または_?":="_と入力して表示されるヘルプページをご覧ください。

32
Josh O'Brien

あなたはこれを行うことができます:

library("stringr")
dt[, -1] <- lapply(dt[, -1], function(x) str_replace(x," ","_"))
7
flodel