2017-01-24 4 views
1

私は5M行のdata.tableオブジェクトを持っています。列が前の行に変更されないdata.tableの行を削除する

csvdata <- data.table(timestamp = c(1:6), 
         signal.a=c(12, 12, 13, 12, 12, 14), 
         signal.b=c(7, 7, 7, 7, 8, 8)) 

timestamp signal.a signal.b 
     1  12   7 
     2  12   7 
     3  13   7 
     4  12   7 
     5  12   8 
     6  14   8 

私がしようとしているのは、信号の変更を登録していないテーブルのすべての行を削除することです。ですから、私はこれで終わりたいと思います:signal.aもsignal.bも変更されていないので、行2は削除されます。

timestamp signal.a signal.b 
     1  12   7 
     3  13   7 
     4  12   7 
     5  12   8 
     6  14   8 

私はRでの経験がほとんどないので、私は削除のために各行をマークし、後で私が維持したい行をフィルタリングするために意図してforループの通常のアプローチを試してみました:

for (i in 1:nrow(csvdata)) { 
    if (i > 1 && csvdata[i]$signal.a == csvdata[i-1]$signal.a && 
     csvdata[i]$signal.b == csvdata[i-1]$signal.b) { 
     csvdata[i]$Drop <- 1 
    } 
} 

コードは機能しているようですが、5M行ではこのコードは永久に実行されます(2時間とカウント)。より効率的なソリューションはありますか?

+0

です単純に重複を削除します。信号が12と7に戻って、タイムスタンプ7で言えば、私はその行を保持したいと思います。 – cddbldot

答えて

3

これにアプローチする一般的な方法の1つは...どちらか(@アルンさんのコメントのおかげで)のようなrleid、と私はできません

csvdata[!duplicated(rleid(signal.a, signal.b))] 

またはusing @eddi's approach ...

csvdata[ csvdata[, .I[1L], by=rleid(signal.a, signal.b)]$V1 ] 
+0

うわー、非常に簡単です。あなたは好きなように列を追加したり削除したりすることもできますが、これはRolandのアプローチでは不可能です(これは私にとってもうまくいきます)。 – cddbldot

+0

@cddbldotわかりません。私のアプローチでは不可能なことは何ですか? – Roland

+0

@Roland方程式に 'signal.c'を追加するか、' signal.b'を落として 'x引数を '|'に渡すことができますそれは2 'を必要とする。私は自分の問題を解決するためにそれを必要としませんでした。私はあなたのコードを変更するだけで、ちょっとしたことを信じています。ここでは、列をリストに追加するだけで済むので、もっと普遍的です(少なくとも直感的です)。 – cddbldot

3
csvdata[csvdata[, c(TRUE, #always keep first row 
        Reduce("|", #at least one column needs to change 
          Map("!=", 
           shift(.(signal.a, signal.b)), #shift the columns by one row 
           .(signal.a, signal.b)) #and compare with preceding row 
          )[-1])] #always keep first row 
     ,] 
# timestamp signal.a signal.b 
#1:   1  12  7 
#2:   3  13  7 
#3:   4  12  7 
#4:   5  12  8 
#5:   6  14  8 
関連する問題