バナナでもわかる話

開設当初は計量経済学・統計学が専門の大学院生でした。今はデータを扱うお仕事をしています。統計学・経済学・投資理論・マーケティング等々に関する勉強・解説ブログ。ときどき趣味も。極力数式は使わずイメージで説明出来るよう心掛けていますが、時々暴走します。

Rで任意の個数の0と1の組み合わせパターンを出力する関数を作る

今回はタイトルのような関数を作ってみたいと思います。
0と1の組み合わせってなんやねんっていうと、例えば2個のもので考えるなら

 (00,01,10,11)

こんな感じ。この組み合わせの総数は 2^{個数}個あるので、手作業で頑張るのは個数が大きくなってくるとしんどいです。
※5個の時点で32パターンあります。

そこで、関数化してみます。

目次

スポンサーリンク



アイデアの種

例えば、先ほどの (00,01,10,11)を次のように縦に並べてみます。
 00
 01
 10
 11

これらの数列を左の項から順番に比べた時に、どの時点で各数列が異なると識別できるのか考えてみます。
例えば最初にある 00 01は初めの数字は同じ0で異なるものかどうかは識別出来ません、次に並ぶ数字を確認して初めて異なる数列であると判断できます。

アルゴリズムのアイデア

もう少し個数の多い例でも見てみます。例えば5個のケース。

      [,1] [,2] [,3] [,4] [,5]
 [1,]    0    0    0    0    0
 [2,]    0    0    0    0    1
 [3,]    0    0    0    1    0
 [4,]    0    0    0    1    1
 [5,]    0    0    1    0    0
 [6,]    0    0    1    0    1
 [7,]    0    0    1    1    0
 [8,]    0    0    1    1    1
 [9,]    0    1    0    0    0
[10,]    0    1    0    0    1
[11,]    0    1    0    1    0
[12,]    0    1    0    1    1
[13,]    0    1    1    0    0
[14,]    0    1    1    0    1
[15,]    0    1    1    1    0
[16,]    0    1    1    1    1
[17,]    1    0    0    0    0
[18,]    1    0    0    0    1
[19,]    1    0    0    1    0
[20,]    1    0    0    1    1
[21,]    1    0    1    0    0
[22,]    1    0    1    0    1
[23,]    1    0    1    1    0
[24,]    1    0    1    1    1
[25,]    1    1    0    0    0
[26,]    1    1    0    0    1
[27,]    1    1    0    1    0
[28,]    1    1    0    1    1
[29,]    1    1    1    0    0
[30,]    1    1    1    0    1
[31,]    1    1    1    1    0
[32,]    1    1    1    1    1

個数は5なので、 2^5=32通りあります。組み合わせを考えれば自明ですが、一番初めの数字が0のパターンは \frac{2^5}{2}=16通り、一番初めの数字が1のパターンも同様に \frac{2^5}{2}=16通りあるはずです。

一番初めの数字が0のパターンだけ試しに抜き出してみます。

      [,1] [,2] [,3] [,4] [,5]
 [1,]    0    0    0    0    0
 [2,]    0    0    0    0    1
 [3,]    0    0    0    1    0
 [4,]    0    0    0    1    1
 [5,]    0    0    1    0    0
 [6,]    0    0    1    0    1
 [7,]    0    0    1    1    0
 [8,]    0    0    1    1    1
 [9,]    0    1    0    0    0
[10,]    0    1    0    0    1
[11,]    0    1    0    1    0
[12,]    0    1    0    1    1
[13,]    0    1    1    0    0
[14,]    0    1    1    0    1
[15,]    0    1    1    1    0
[16,]    0    1    1    1    1

今度は一つ目の数字は皆同じなので二つ目の数字を見てみます。先ほどと同様に16パターンのうち、二つ目の数字が0であるパターンは \frac{16}{2}=8個のはずです。


この操作を順々に繰り返していくと結局、総パターンの内、左から見ていった時に k個目までが同じ数列であるパターン数は \frac{2^{個数}}{2^k}個であると考えられます。

関数化

さて、今の手順を関数化してみることにします。

subsetfun=function(kosuu){
	XX=matrix(,2^kosuu,kosuu)
	for(i in 1:kosuu){
		CCC=t(rbind(rep(0,2^(kosuu-i)),rep(1,2^(kosuu-i))))
		XX[,i]=rep(CCC,2^(i-1))
	}
	return(XX)
}

試しに、個数=6で出力してみます。

> subsetfun(6)
      [,1] [,2] [,3] [,4] [,5] [,6]
 [1,]    0    0    0    0    0    0
 [2,]    0    0    0    0    0    1
 [3,]    0    0    0    0    1    0
 [4,]    0    0    0    0    1    1
 [5,]    0    0    0    1    0    0
 [6,]    0    0    0    1    0    1
 [7,]    0    0    0    1    1    0
 [8,]    0    0    0    1    1    1
 [9,]    0    0    1    0    0    0
[10,]    0    0    1    0    0    1
[11,]    0    0    1    0    1    0
[12,]    0    0    1    0    1    1
[13,]    0    0    1    1    0    0
[14,]    0    0    1    1    0    1
[15,]    0    0    1    1    1    0
[16,]    0    0    1    1    1    1
[17,]    0    1    0    0    0    0
[18,]    0    1    0    0    0    1
[19,]    0    1    0    0    1    0
[20,]    0    1    0    0    1    1
[21,]    0    1    0    1    0    0
[22,]    0    1    0    1    0    1
[23,]    0    1    0    1    1    0
[24,]    0    1    0    1    1    1
[25,]    0    1    1    0    0    0
[26,]    0    1    1    0    0    1
[27,]    0    1    1    0    1    0
[28,]    0    1    1    0    1    1
[29,]    0    1    1    1    0    0
[30,]    0    1    1    1    0    1
[31,]    0    1    1    1    1    0
[32,]    0    1    1    1    1    1
[33,]    1    0    0    0    0    0
[34,]    1    0    0    0    0    1
[35,]    1    0    0    0    1    0
[36,]    1    0    0    0    1    1
[37,]    1    0    0    1    0    0
[38,]    1    0    0    1    0    1
[39,]    1    0    0    1    1    0
[40,]    1    0    0    1    1    1
[41,]    1    0    1    0    0    0
[42,]    1    0    1    0    0    1
[43,]    1    0    1    0    1    0
[44,]    1    0    1    0    1    1
[45,]    1    0    1    1    0    0
[46,]    1    0    1    1    0    1
[47,]    1    0    1    1    1    0
[48,]    1    0    1    1    1    1
[49,]    1    1    0    0    0    0
[50,]    1    1    0    0    0    1
[51,]    1    1    0    0    1    0
[52,]    1    1    0    0    1    1
[53,]    1    1    0    1    0    0
[54,]    1    1    0    1    0    1
[55,]    1    1    0    1    1    0
[56,]    1    1    0    1    1    1
[57,]    1    1    1    0    0    0
[58,]    1    1    1    0    0    1
[59,]    1    1    1    0    1    0
[60,]    1    1    1    0    1    1
[61,]    1    1    1    1    0    0
[62,]    1    1    1    1    0    1
[63,]    1    1    1    1    1    0
[64,]    1    1    1    1    1    1

うまくいっていますね。

コメント

この関数、なんで作ろうかと思ったかというと、線形回帰の変数選択の自動化をしたかったから書きました。次回にでも変数選択の自動化関数についても書いてみたいと思います。

ちなみにyahoo知恵袋にてこんな質問が落ちていました。
4桁かつ、0と1の組み合わせ - 0と1からなる4桁の数字の組み合わせはどれく... - Yahoo!知恵袋
この手の質問もこの関数ならすぐに視覚的に見せることが出来ますね。