web-dev-qa-db-ja.com

2つのベクトル間で重複しない要素を見つける

他のベクターに含まれていない要素を特定しようとしています。例えば私が持っている2つのベクトルで

list.a <- c("James", "Mary", "Jack", "Sonia", "Michelle", "Vincent")

list.b <- c("James", "Sonia", "Vincent")

どの人が重なっていないかを確認する方法はありますか?この例では、Mary、Jack、およびMichelleを含むベクトル結果を取得します。

どんな提案も役立ちます!

16
song0089

はい、方法があります:

setdiff(list.a, list.b)
# [1] "Mary"     "Jack"     "Michelle"
28
Julius Vainora

申し立てられた答えは部分的にしか正しくないことに言及すべきだと思います。コマンドsetdiff(list.a, list.b)は、重複しない要素を検索しますこれらの要素が最初の引数として使用されるオブジェクトに含まれている場合のみ!。

この動作を認識しておらず、代わりにsetdiff(list.b, list.a)を実行した場合、この場合の結果はcharacter(0)となり、重複しない要素がないと結論付けることになります。

説明のために少し拡張した例を使用すると、明らかなクイックフィックスは次のとおりです。

list.a <- c("James", "Mary", "Jack", "Sonia", "Michelle", "Vincent")
list.b <- c("James", "Sonia", "Vincent", "Iris")

c(setdiff(list.b, list.a), setdiff(list.a, list.b))
# [1] "Iris"     "Mary"     "Jack"     "Michelle" 
12
Manuel R

Hadleyと私自身のコメントに基づく拡張回答:重複を許可する方法は次のとおりです。

最終編集:期待どおりの結果が得られない可能性があるため、これを使用することはお勧めしません。 xにはないがyに繰り返される値がある場合、その値が出力に繰り返されます。しかし、たとえば、4つの9s in xおよび1つの9y、すべての9sは削除されます。それらの3つを保持することを期待するかもしれません。面倒なコードが必要です。

mysetdiff<-function (x, y, multiple=FALSE) 
{
    x <- as.vector(x)
    y <- as.vector(y)
    if (length(x) || length(y)) {
        if (!multiple) {
             unique( x[match(x, y, 0L) == 0L])  
              }else  x[match(x, y, 0L) == 0L] 
        } else x
}

Rgames> x
[1]  8  9  6 10  9
Rgames> y
[1] 5 3 8 8 1
Rgames> setdiff(x,y)
[1]  9  6 10
Rgames> mysetdiff(x,y)
[1]  9  6 10
Rgames> mysetdiff(x,y,mult=T)
[1]  9  6 10  9
Rgames> mysetdiff(y,x,mult=T)
[1] 5 3 1
Rgames> setdiff(y,x)
[1] 5 3 1
3
Carl Witthoft

重複に適用される素敵なワンライナー:

anti_join(data_frame(c(1,1,2,2)), data_frame(c(1,1)))

これにより、データフレーム{2,2}が返されます。ただし、これは2回検出されるため、1,1,2,2の1,2の場合には適用されません。

2
Noale