web-dev-qa-db-ja.com

expand.gridの非冗長バージョン

R関数expand.gridは、指定されたパラメーターの要素間のすべての可能な組み合わせを返します。例えば.

> expand.grid(c("aa", "ab", "cc"), c("aa", "ab", "cc"))
  Var1 Var2
1   aa   aa
2   ab   aa
3   cc   aa
4   aa   ab
5   ab   ab
6   cc   ab
7   aa   cc
8   ab   cc
9   cc   cc

提供されたベクトル間の「一意の」組み合わせのみを直接(つまりexpand.gridの後に行を比較せずに)取得する効率的な方法を知っていますか?出力は

  Var1 Var2
1   aa   aa
2   ab   aa
3   cc   aa
5   ab   ab
6   cc   ab
9   cc   cc

[〜#〜] edit [〜#〜]各要素とそれ自体の組み合わせは、最終的に回答から破棄される可能性があります。 (数学的に)aa aaVar1の1つの要素とvar2の別の要素の間の(通常の)一意の組み合わせですが、実際にはプログラムで必要ありません。

ソリューションは両方のベクトルから要素のペアを生成する必要があります(つまり、各入力ベクトルから1つを作成し、2つ以上の入力に適用できるようにします)。

36
Michele

outerを使ってみませんか?しかし、この特定の関数はそれらを1つの文字ストリングに連結します。

outer( c("aa", "ab", "cc"), c("aa", "ab", "cc") , "paste" )
#     [,1]    [,2]    [,3]   
#[1,] "aa aa" "aa ab" "aa cc"
#[2,] "ab aa" "ab ab" "ab cc"
#[3,] "cc aa" "cc ab" "cc cc"

繰り返し要素が必要ない場合は、2つのベクトルの一意の要素に対してcombnを使用することもできます(例:aa aa

vals <- c( c("aa", "ab", "cc"), c("aa", "ab", "cc") )
vals <- unique( vals )
combn( vals , 2 )
#     [,1] [,2] [,3]
#[1,] "aa" "aa" "ab"
#[2,] "ab" "cc" "cc"
28
Simon O'Hanlon

ベースRでは、これを使用できます。

expand.grid.unique <- function(x, y, include.equals=FALSE)
{
    x <- unique(x)

    y <- unique(y)

    g <- function(i)
    {
        z <- setdiff(y, x[seq_len(i-include.equals)])

        if(length(z)) cbind(x[i], z, deparse.level=0)
    }

    do.call(rbind, lapply(seq_along(x), g))
}

結果:

> x <- c("aa", "ab", "cc")
> y <- c("aa", "ab", "cc")

> expand.grid.unique(x, y)
     [,1] [,2]
[1,] "aa" "ab"
[2,] "aa" "cc"
[3,] "ab" "cc"

> expand.grid.unique(x, y, include.equals=TRUE)
     [,1] [,2]
[1,] "aa" "aa"
[2,] "aa" "ab"
[3,] "aa" "cc"
[4,] "ab" "ab"
[5,] "ab" "cc"
[6,] "cc" "cc"
14
Ferdinand.kraft

2つのベクトルが同じ場合は、combinationsパッケージにgtools関数があります。

library(gtools)
combinations(n = 3, r = 2, v = c("aa", "ab", "cc"), repeats.allowed = TRUE)

#      [,1] [,2]
# [1,] "aa" "aa"
# [2,] "aa" "ab"
# [3,] "aa" "cc"
# [4,] "ab" "ab"
# [5,] "ab" "cc"
# [6,] "cc" "cc"

そして"aa" "aa"などなし.

combinations(n = 3, r = 2, v = c("aa", "ab", "cc"), repeats.allowed = FALSE)
13
BenBarnes

以前の回答には、特定の結果を取得する方法がありませんでした。つまり、自己ペアを維持しながら、順序が異なるものを削除する方法がありませんでした。 gtoolsパッケージには、これらの目的のためにcombinationspermutationsの2つの関数があります。 このウェブサイトによると

  • 順序が関係ない場合は、組み合わせです。
  • 順序が重要な場合は、順列です。

どちらの場合も、繰り返しを許可するかどうかを決定します。それに応じて、両方の関数に_repeats.allowed_引数があり、4つの組み合わせが生成されます(おいしくメタです)。これらのそれぞれについて検討する価値があります。わかりやすくするために、ベクトルを1文字に簡略化しました。

繰り返しのある順列

最も広範なオプションは、自己関係と順序が異なるオプションの両方を許可することです。

_> permutations(n = 3, r = 2, repeats.allowed = T, v = c("a", "b", "c"))
      [,1] [,2]
 [1,] "a"  "a" 
 [2,] "a"  "b" 
 [3,] "a"  "c" 
 [4,] "b"  "a" 
 [5,] "b"  "b" 
 [6,] "b"  "c" 
 [7,] "c"  "a" 
 [8,] "c"  "b" 
 [9,] "c"  "c" 
_

9つのオプションがあります。この値は、単純な式_n^r_、つまり_3^2=9_から見つけることができます。これは デカルト積/結合 であり、SQLに精通したユーザー向けです。

これを制限する方法は2つあります。1)自己関係を削除する(繰り返しを禁止する)、または2)順序が異なるオプション(つまり、組み合わせ)を削除する。

繰り返しの組み合わせ

順序が異なるオプションを削除したい場合は、次のようにします。

_> combinations(n = 3, r = 2, repeats.allowed = T, v = c("a", "b", "c"))
     [,1] [,2]
[1,] "a"  "a" 
[2,] "a"  "b" 
[3,] "a"  "c" 
[4,] "b"  "b" 
[5,] "b"  "c" 
[6,] "c"  "c" 
_

これには6つのオプションがあります。この値の式は_(r+n-1)!/(r!*(n-1)!)_、つまり_(2+3-1)!/(2!*(3-1)!)=4!/(2*2!)=24/4=6_です。

繰り返しのない順列

代わりに繰り返しを禁止したい場合は、以下を使用します。

_> permutations(n = 3, r = 2, repeats.allowed = F, v = c("a", "b", "c"))
     [,1] [,2]
[1,] "a"  "b" 
[2,] "a"  "c" 
[3,] "b"  "a" 
[4,] "b"  "c" 
[5,] "c"  "a" 
[6,] "c"  "b" 
_

これも6つのオプションを提供しますが、オプションは異なります。オプションの数は上記と同じですが、偶然です。値は、式n!/(n-r)!、つまり_(3*2*1)/(3-2)!=6/1!=6_から取得できます。

繰り返しのない組み合わせ

最も制限があるのは、自己関係/繰り返しや順序の異なるオプションのどちらも必要ない場合です。この場合、次のように使用します。

_> combinations(n = 3, r = 2, repeats.allowed = F, v = c("a", "b", "c"))
     [,1] [,2]
[1,] "a"  "b" 
[2,] "a"  "c" 
[3,] "b"  "c" 
_

オプションは3つしかありません。オプションの数は、かなり複雑な式n!/(r!(n-r)!)、つまり3*2*1/(2*1*(3-2)!)=6/(2*1!)=6/2=3から計算できます。

8
Deleet

試してください:

factors <- c("a", "b", "c")

all.combos <- t(combn(factors,2))

     [,1] [,2]
[1,] "a"  "b" 
[2,] "a"  "c" 
[3,] "b"  "c"

これには各要素の重複(「a」「a」など)は含まれませんが、必要に応じて簡単に追加できます。

dup.combos <- cbind(factors,factors)

     factors factors
[1,] "a"     "a"    
[2,] "b"     "b"    
[3,] "c"     "c"   

all.combos <- rbind(all.combos,dup.combos)

     factors factors
[1,] "a"     "b"    
[2,] "a"     "c"    
[3,] "b"     "c"    
[4,] "a"     "a"    
[5,] "b"     "b"    
[6,] "c"     "c" 
8
EvH

「より大きい」演算を使用して、冗長な組み合わせをフィルタリングできます。これは、数値ベクトルと文字ベクトルの両方で機能します。

> grid <- expand.grid(c("aa", "ab", "cc"), c("aa", "ab", "cc"), stringsAsFactors = F)
> grid[grid$Var1 >= grid$Var2, ]
  Var1 Var2
1   aa   aa
2   ab   aa
3   cc   aa
5   ab   ab
6   cc   ab
9   cc   cc

これによってコードの処理速度が遅くなることはありません。大きな要素を含むベクトル(データフレームの2つのリストなど)を展開する場合は、元のベクトルを参照する数値インデックスを使用することをお勧めします。

1
Daniel Freeman