2016-08-21 8 views
4

この質問はHow can I quickly see if any elements of multiple vectors are equal in R?によって引き起こされますが、同一ではありません。小さな例として`%in% 'のようなペアワイズ操作を実行し、ベクトルのリストに対して操作を設定する方法

、我々は4つのベクトルのリストを持っているとします

set.seed(0) 
lst <- list(vec1 = sample(1:10, 2, TRUE), vec2 = sample(1:10, 3, TRUE), 
      vec3 = sample(1:10, 4, TRUE), vec4 = sample(1:10, 5, TRUE)) 

はどのように我々は%in%と集合演算などのペアごとのバイナリ操作を行うことができますがintersectunionsetdiffを言うの?

pairwise "%in%"が必要な場合、それぞれのペア内でさらにany()/all()/which()を実行するにはどうすればよいですか?

注:combn()は使用しません。

+1

ない直接適用はなく、似たようなケースでは、古典的な 'テーブル/(T)crossprod'アプローチは、いくつかのペアごとの関係を明らかにすることができ - ' crossprodを(:私たちは、結果のリストの名の組み合わせのインデックスを使用することができますテーブル(val = unlist(lst、、FALSE)、vec = rep(seq_along(lst)、lengths(lst)))) 'しかし、すべてを集計することで、メモリの限界によって問題が生じる可能性があります –

答えて

4

outer(x, y, FUN)を使用できます。 xyは数値ベクトル/行列のように "数値"入力である必要はありません。 "list"/"matrix list"のようなベクトル入力も許されます。

は、例えば、我々は、それ自体がベクトル化されていない"%in%"ため

z <- outer(lst, lst, FUN = Vectorize("%in%", SIMPLIFY = FALSE, USE.NAMES = FALSE)) 
#  vec1  vec2  vec3  vec4  
#vec1 Logical,2 Logical,2 Logical,2 Logical,2 
#vec2 Logical,3 Logical,3 Logical,3 Logical,3 
#vec3 Logical,4 Logical,4 Logical,4 Logical,4 
#vec4 Logical,5 Logical,5 Logical,5 Logical,5 

を使用ペアワイズ"%in%"動作を適用するために、我々はVectorized("%in%")を使用します。 FUNが各ペアの長さ1リストを返すように、SIMPLIFY = FALSEも必要です。(x[[i]], y[[j]])

y[[4]] | FUN(x[[1]], y[[4]]) FUN(x[[2]], y[[4]]) FUN(x[[1]], y[[4]]) FUN(x[[2]], y[[4]]) 
y[[3]] | FUN(x[[1]], y[[3]]) FUN(x[[2]], y[[3]]) FUN(x[[1]], y[[3]]) FUN(x[[2]], y[[4]]) 
y[[2]] | FUN(x[[1]], y[[2]]) FUN(x[[2]], y[[2]]) FUN(x[[1]], y[[2]]) FUN(x[[2]], y[[4]]) 
y[[1]] | FUN(x[[1]], y[[1]]) FUN(x[[2]], y[[1]]) FUN(x[[1]], y[[1]]) FUN(x[[2]], y[[4]]) 
     ------------------- ------------------- ------------------- ------------------- 
     x[[1]]    x[[2]]    x[[3]]    x[[4]] 

それはlength(FUN(x, y)) == length(x) * length(y)ことを確認しなければならない:outer作品が好きなように、これは重要です。 SIMPLIFY = FALSEの場合、これは必ずしも成立しません。

上記の結果zは「マトリックスリスト」であり、class(z)は「マトリックス」ですが、typeof(z)は「リスト」です。詳細はWhy is this matrix not numeric?をご覧ください。


我々はさらにzの各要素にいくつかの要約機能を適用したい場合は、我々はlapplyを使用することができます。ここでは2つの例を提供します。

例1:any(a %in% b)のでany()

を適用すなわち、操作が対称である、any(b %in% a)と同じようで、我々は唯一のzの下三角で作業する必要があります。

lz <- z[lower.tri(z)] 

lapply名前のないリストを返しますが、読みやすくするために名前付きリストが必要です。私たちは、名前のように行列インデックス(i, j)を使用することがあります。我々は、同様に動作することができます対称操作も

ind <- which(lower.tri(z), arr.ind = TRUE) 
NAME <- paste(ind[,1], ind[,2], sep = ":") 
any_lz <- setNames(lapply(lz, any), NAME) 

#List of 6 
# $ 2:1: logi FALSE 
# $ 3:1: logi TRUE 
# $ 4:1: logi TRUE 
# $ 3:2: logi TRUE 
# $ 4:2: logi FALSE 
# $ 4:3: logi TRUE 

Set操作をintersectunionsetequalのようなものです。

例2:適用which()

which(a %in% b)が対称操作ではありませんので、我々は完全な行列と仕事をしなければなりません。

NAME <- paste(1:nrow(z), rep(1:nrow(z), each = ncol(z)), sep = ":") 
which_z <- setNames(lapply(z, which), NAME) 

# List of 16 
# $ 1:1: int [1:2] 1 2 
# $ 2:1: int(0) 
# $ 3:1: int [1:2] 1 2 
# $ 4:1: int 3 
# $ 1:2: int(0) 
# $ 2:2: int [1:3] 1 2 3 
# ... 

setdiffなどの設定操作も非対称であり、同様に処理することができます。


代替

別にouter()を使用してから、我々はまた、上記のzを得るために、Rの表現を使用することができます。繰り返しますが、私は、一例として、二項演算"%in%"を取る:

op <- "'%in%'" ## operator 

lst_name <- names(lst) 
op_call <- paste0(op, "(", lst_name, ", ", rep(lst_name, each = length(lst)), ")") 
# [1] "'%in%'(vec1, vec1)" "'%in%'(vec2, vec1)" "'%in%'(vec3, vec1)" 
# [4] "'%in%'(vec4, vec1)" "'%in%'(vec1, vec2)" "'%in%'(vec2, vec2)" 
# ... 

その後、我々はlst内でこれらの式を解析し、評価することができます。ここではおそらく

NAME <- paste(1:length(lst), rep(1:length(lst), each = length(lst)), sep = ":") 
z <- setNames(lapply(parse(text = op_call), eval, lst), NAME) 

# List of 16 
# $ 1:1: logi [1:2] TRUE TRUE 
# $ 2:1: logi [1:3] FALSE FALSE FALSE 
# $ 3:1: logi [1:4] TRUE TRUE FALSE FALSE 
# $ 4:1: logi [1:5] FALSE FALSE TRUE FALSE FALSE 
# $ 1:2: logi [1:2] FALSE FALSE 
# ... 
関連する問題