2012-01-07 4 views
3

私はRが新しく、以下のコードで何が間違っているのか、どのように高速化できるか把握できません。 私はデータセットを持っており、2列のデータから計算された平均値を含む列を追加したいと考えています。以下のコードを見てみてください(警告:これは私の質問を読むためにいくつかの時間がかかることがありますが、コードはRで正常に動作):最初の一部のハッシュマップメソッドを使用してデータフレーム列を効率的に更新するR

を私はDFは(再び私は長い説明をお詫びデータセットを定義してみましょうコード)

> df<-data.frame(prediction=sample(c(0,1),10,TRUE),subject=sample(c("car","dog","man","tree","book"),10,TRUE)) 
> df 
    prediction subject 
1   0  man 
2   1  dog 
3   0  man 
4   1 tree 
5   1  car 
6   1 tree 
7   1  dog 
8   0 tree 
9   1 tree 
10   1 tree 

次に私は、新しい列が電話交換するように、私はrateMapを生成する新しいテーブル定義から

df$subjectRate <- with(df,ave(prediction,subject)) 
> df 
     prediction subject subjectRate 
    1   0  man   0.0 
    2   1  dog   1.0 
    3   0  man   0.0 
    4   1 tree   0.8 
    5   1  car   1.0 
    6   1 tree   0.8 
    7   1  dog   1.0 
    8   0 tree   0.8 
    9   1 tree   0.8 
    10   1 tree   0.8 

したdfするsubjectRateと呼ばれる追加します以前に得られた平均値で初期化されたsubjectRate列で新しいデータを書き込む。どのように効率的に3番目の列を作成します:

rateMap <- df[!duplicated(df[, c("subjectRate")]), c("subject","subjectRate")] 
> rateMap 
    subject subjectRate 
1  man   0.0 
2  dog   1.0 
4 tree   0.8 

は今、私は

> dfNew<-data.frame(prediction=sample(c(0,1),15,TRUE),subject=sample(c("car","dog","man","cat","book","computer"),15,TRUE)) 
> dfNew 
    prediction subject 
1   1  man 
2   0  cat 
3   1 computer 
4   0  dog 
5   0  book 
6   1  cat 
7   1  car 
8   0  book 
9   0 computer 
10   1  dog 
11   0  cat 
12   0  book 
13   1  dog 
14   1  man 
15   1  dog 

DFと新しい科目に古い主題の組み合わせで私の質問を新しいデータセットを定義するのですか?現在私は地図の主題レートを調べて見つかった場合は値を入力し、そうでない場合は0.5を入力します。

> all_facts<-levels(factor(rateMap$subject)) 
> dfNew$subjectRate <- sapply(dfNew$subject,function(t) ifelse(t %in% all_facts,rateMap[as.character(rateMap$subject) == as.character(t),][1,"subjectRate"],0.5)) 
> dfNew 
    prediction subject subjectRate 
1   1  man   0.0 
2   0  cat   0.5 
3   1 computer   0.5 
4   0  dog   1.0 
5   0  book   0.5 
6   1  cat   0.5 
7   1  car   0.5 
8   0  book   0.5 
9   0 computer   0.5 
10   1  dog   1.0 
11   0  cat   0.5 
12   0  book   0.5 
13   1  dog   1.0 
14   1  man   0.0 
15   1  dog   1.0 

が、平均を計算する被写体と同様の複数の列の実際のデータセット(20万の以上の行)と、コードの実行に非常に長い時間を要します。誰かが私が達成しようとしていることをやるより良い方法を提案することができますか?多分いくつかのマージや何か、私はアイデアがありません。 ありがとうございます。

答えて

6

私はこれが速くなると思われる(しかし、私はそれをテストしていないので、わからない):

dfNew$subjectRate <- rateMap$subjectRate[match(dfNew$subject,rateMap$subject)] 

それは主にだけインデックスとmatchを使用しているため。確かに少しシンプルだと思います。 ave作品が特に遅い場合これは、NAのではなく、0.5、そしてあなたが好きしかし、中に充填することができ、

dfNew$subjectRate[is.na(dfNew$subjectRate)] <- newValue 

で「新しい」の値で、これらの日は、にある標準勧告を記入しますdata.tableパッケージを使用します。

require(data.table) 
dft <- as.data.table(df) 
setkeyv(dft, "subject") 
dft[, subjectRate := mean(prediction), by = subject] 

をし、これはおそらく最後の行にそのデータ・テーブル・アグリゲーションのうち、もう少しスピードをEKEする方法を示唆いくつかのコメントを誘致します。実際には、純粋なdata.tablesを使用したマージまたは結合は、より滑らかで(高速でもよい)、そのオプションを調べることもできます。 (一連の例については、?data.tableの最下部を参照してください)

+0

ありがとうございました。これまでは投稿した最初の2つのコードスニペットのみを使用していましたが、今は文字通りすべてを処理するのに1秒未満しかかかりません。私は間違いなくdata.tableも見ていきます。 – ak3nat0n

+1

こんにちは。私は当時これを逃した。最後の行は、グループごとに ':='が実装されている場合、 'dft [、subjectRate:= mean(prediction)、by = subject]'のように、はるかに高速で洗練されたものになります。 –

関連する問題