2016-07-14 9 views
1

data.tableに行を適用しようとしていますが、それを動作させることはできません。どうすればいいですか?行が列番号参照でdata.tableに適用されます

library(data.table) 
data(diamonds, package= "ggplot2") 
dt <- data.table(diamonds) 

# what I want, but via data.table 
diamonds$sum1 <- apply(dt[,5:10, with=FALSE], 1, sum) 
diamonds$sd1 <- apply(dt[,5:10, with=FALSE], 1, sd) 

# why don't these work? 
dt[, `:=` (sum1= sum(.SD), 
      sd1= sd(.SD)), .SDcols= 5:10, by= .EACHI] 
dt[, `:=` (sum1= sum(dt[,5:10, with=FALSE]), 
      sd1= sd(dt[,5:10, with=FALSE])), by= .EACHI] 

はどちらも、このエラーを与える:

Error in [.data.table (dt, , := (sum1 = sum(.SD), sd1 = sd(.SD)), .SDcols = 5:10, : object 'f__' not found

関連

ではなく、同じ質問:(1)(2)

+1

'by = .EACHI'のどこかにあなたが望むことをするためのFRがありますが、現時点では参加時に意味があります。必要なら 'by = 1:nrow(dt)'を使ってください。 – eddi

+1

一般的な行の行為を避けるようにしてください。あなたは単に 'melt'を使って長い形式に変換してから、単一の列で操作することができます。あるいは、 'rowMeans'を実行するか、他の多くの行操作でベクトル化された' matrixStats'をチェックアウトすることができます。または、[自分の](http://stackoverflow.com/a/25100036/3001626)ベクター化された関数を記述します。またはRcppを使用します。私が見ているように、Rは、あなたの問題を効率的に解決するためにスマートな技を発明する必要がある言語であり、最初のサイトで最も理にかなっています。 –

+0

@DavidArenburg十分な点があります。しかし、これをRcppに書き込むdevの時間は、 'data.frame'フレームワークを使用するだけの価値はありません。 –

答えて

0

これは、その後でC++での高速な関数を記述するためにRcppパッケージを使用していますRから電話をかけることができますが、それは合理的にはっきりとして維持可能だと思います。

library(Rcpp) 

cppFunction('Rcpp::NumericVector SDrowSums(Rcpp::DataFrame SD) { 
    Rcpp:: NumericVector sums; 
    for(int i = 0; i<SD.nrows(); ++i) { // each row of .SD 
     sums.push_back( 0.0 
      + as<NumericVector>(SD[4]) [i] 
      + as<NumericVector>(SD[5]) [i] 
      + as<IntegerVector>(SD[6]) [i] // IntegerVector, or will be slow! 
      + as<NumericVector>(SD[7]) [i] 
      + as<NumericVector>(SD[8]) [i] 
      + as<NumericVector>(SD[9]) [i] 
     ); 
    } 
    return sums; 
}'); 

dt[, "sumNew" := SDrowSums(.SD) ,by=seq_len(nrow(dt))] 

最後の行は、テーブルの各行(by=seq_len(nrow(dt)))に対して一度関数SDrowSumsを呼び出します。

私にとっては、約0.15秒で実行されます。 rowSums(私にとっては0.01s)ほど速くはありませんが、元のコードと同じ速度:diamonds$sum1 <- apply(dt[,5:10, with=FALSE], 1, sum)

あなたも、名前("depth""table"、...)と(ゼロベース)列オフセット(456789)を置き換えることができます。これは少し減速しますが、読みやすくなります。

実際にはとSDrowSumsが1行ごとに1つ呼び出されますが、このcpp関数は複数行のSDを許容するために少し一般的です。

+1

ありがとう!私は内部ループがあなたの解決策を改善すると考えています(より一般的なものにします)。 '... for(int j = 0; n

関連する問題