2016-09-23 16 views
3

データフレームから重複行を削除しようとしています。前の行のみに基づいています。 duplicateuniqueの関数はすべての重複を削除し、あなたには一意の行しか残さず、これは私が望むものではありません。前の行のみに基づいて重複行を削除します。

私はこの問題をループで説明しました。実際のデータセットはループを使用するためにはるかに大きいので、これをベクトル化する必要があります。

x <- c(1,1,1,1,3,3,3,4) 
y <- c(1,1,1,1,3,3,3,4) 
z <- c(1,2,1,1,3,2,2,4) 
xy <- data.frame(x,y,z) 

xy 
    x y z 
1 1 1 1 
2 1 1 2 
3 1 1 1 
4 1 1 1 #this should be removed 
5 3 3 3 
6 3 3 2 
7 3 3 2 #this should be removed 
8 4 4 4 

# loop that produces desired output 
toRemove <- NULL 
for (i in 2:nrow(xy)){ 
    test <- as.vector(xy[i,] == xy[i-1,]) 
    if (!(FALSE %in% test)){ 
     toRemove <- c(toRemove, i) #build a vector of rows to remove 
    } 
} 
xy[-toRemove,] #exclude rows 
    x y z 
1 1 1 1 
2 1 1 2 
3 1 1 1 
5 3 3 3 
6 3 3 2 
8 4 4 4 

私はdplyrのlag機能を使用してみましたが、私はそれが動作しない、すべての3つの列の上にそれを実行しようとすると、それだけで、単一の列に取り組んでいます。

ifelse(xy[,1:3] == lag(xy[,1:3],1), NA, xy[,1:3])

これを実現する方法上の任意のアドバイスはありますか?私たちは、行は上記と同じである場合、削除するよう

+0

zx8754のアプローチは確かに行く方法です。しかし、 'mutly_each'を使う限り、' dplyr :: lag'でこれを行うことができます。たとえば、 'xy%>% mutate_each(funs(oneL = .lag(。)))%>% mutate(dup = rowSums(select、。、containsL))))%>% select(x、y、z) ' –

答えて

5

はルックス:

# make an index, if cols not same as above 
ix <- c(TRUE, rowSums(tail(xy, -1) == head(xy, -1)) != ncol(xy)) 

# filter 
xy[ix, ] 
+0

これは機能しますが、構文、特に'!= ncol(xy) 'の部分を説明できますか?私はそれが何とか等価性テストのデータフレームをベクトルに変換することを見ていますが、どのように動作するのか分かりません)私はrowSumsが同じ合計値を持つ行を削除することを期待していました。しかし、私はこれが真であり、このメソッドがそれらの行を削除しなかったいくつかのケースをテストしました。 –

+0

私は 'keep'リストを作成しています。 TRUEで始まる最初の値は、最初の値を維持します。次に、以前と比較して各行の行数を確認します.ncol(この場合は3)と同じではない場合は、保持します。つまり、上記と同じではない行を保持します。これは明らかです。 – zx8754

-2

巣の行にそれをconpareする前の行のトラックを維持しながら、あなただけのリストを反復tはなぜ。 これは、ある時点で該当する場合:行の位置を覚えてリストから削除し、リストの先頭から反復を開始します。 bcuzを反復処理中に行を削除しないと、同時変更エラーが発生します。

+0

ようこそ!あなたが概説したアプローチは、zx8754アプローチに比べて非常に非効率的です。 'R'は高水準言語なので、ループは避けるべきです。特に、BLASを利用するサブセット化は超高速であるため、また、コードを提供した場合は、OPに役立つでしょう。 –

関連する問題