私はこのようなリストを持っているとしましょう:['a','b','c']
。このリストから無作為に組み合わせる必要があります。例えば、['a','c']
です。しかし、私はすべての組み合わせが等しい確率を持つようにする必要がありますので、['a']
を得る機会は、['b','c']
を得るチャンスとまったく同じでなければなりません。私の実際のリストは22要素で、すべての組み合わせを列挙することは不可能です。私の最初の考えはrandom.sampleを使用することでしたが、ランダムに選択する必要がある要素の数を指定する必要がありましたが、確率は(この組み合わせの要素の数)/(すべての組み合わせの要素の数)これは巨大な数字です。もっと良い方法はありますか?これは何千回も実行されるので、効率的なソリューションが評価されます。pythonのリストからランダムに、同じように考えられる組み合わせを生成する
答えて
これを行うには非常に効率的な方法があります。与えられたセットのすべての組み合わせのセットは、power setと呼ばれ、与えられたセットのすべてのサブセットのセットです。集合Sがm個の項目を含む場合、空集合とS自体を含めて合計で2**m
の組み合わせが可能です。
Sのパワーセットからランダムに選択するには、range(2**m)
の乱数nをパワーセットのインデックスとして選択し、nに対応する組み合わせを生成するだけです。
nのバイナリ展開を見て、インデックス番号nを組み合わせに変換できます。 nにはmビットがあります。これらのビットをSのアイテムとペアリングします。ビットが1の場合、そのアイテムが選択され、0の場合はそのアイテムが拒否されます。
ここで短いデモです。
from random import seed, randrange
seed(42)
def indexed_combination(seq, n):
result = []
for u in seq:
if n & 1:
result.append(u)
n >>= 1
if not n:
break
return result
print('Testing indexed_combination')
seq = 'abc'
for i in range(1 << len(seq)):
print(i, ''.join(indexed_combination(seq, i)))
print()
def random_combination(seq):
n = randrange(1 << len(seq))
return indexed_combination(seq, n)
print('Testing random_combination')
seq = 'abcdefghij'
for i in range(20):
print(i, random_combination(seq))
出力
Testing indexed_combination
0
1 a
2 b
3 ab
4 c
5 ac
6 bc
7 abc
Testing random_combination
0 ['c', 'f', 'g', 'h']
1 ['a', 'b', 'e', 'f']
2 ['a', 'b', 'e', 'f', 'j']
3 ['a', 'c', 'e', 'f', 'g', 'h', 'i']
4 ['a', 'd', 'g', 'h', 'i']
5 ['a', 'c', 'd', 'e', 'i']
6 ['a', 'e', 'g', 'h']
7 ['b', 'e', 'f', 'h']
8 ['f', 'g', 'i', 'j']
9 ['a', 'g']
10 ['a', 'c', 'd', 'e', 'f']
11 ['a', 'b', 'c', 'd', 'e', 'f', 'h']
12 ['a', 'b', 'c', 'd', 'e', 'f', 'h', 'i']
13 ['c', 'd', 'e', 'g', 'h', 'i']
14 ['b', 'c', 'e', 'f']
15 ['a', 'b', 'c', 'e', 'h', 'i']
16 ['a', 'b', 'd', 'e', 'g', 'i', 'j']
17 ['a', 'b', 'g', 'h', 'i']
18 ['a', 'b', 'c', 'e', 'h', 'i', 'j']
19 ['a', 'd', 'e', 'f', 'j']
Iは、固定されたシード番号とスクリプトの開始時にランダムseed
関数を呼び出します。擬似乱数を使用するコードを開発するときは、乱数が再現可能なときにコードをテストしてデバッグするのが簡単になるため、これを行うと便利です。実際のアプリケーションでは、システムのエントロピーソースをラドマイザーに設定する必要があります。 seed
コールを削除するか、seed(None)
を実行して簡単に行うことができます。標準のMersenee Twisterジェネレータが提供するものよりもランダム性が必要な場合は、random.SystemRandom
クラスを使用してシステムのランダムソースにフックすることができます。
これは優れた答えであり、受け入れられるべきだと私は思っています。 [質問へのコメントを見る](https://stackoverflow.com/questions/47234958/generate-a-random-equally-probable-combination-from-a-list-in-python#comment81443547_47234958) – piRSquared
combination
を使用して、nを選択するための繰り返し可能性を作成し、chain
を使用して、i = 1〜nのすべての組み合わせを組み合わせます。組み合わせの合計数は2 ** n - 1
になるので、0から2 ** n - 2までのランダムな整数を選択します。最後に、islice
を使用して、繰り返し可能な値からその値を抜き取ってください。
from itertools import islice, combinations, chain
from string import ascii_uppercase
def pickcomb(i):
n = len(i)
allcomb = chain(*(combinations(i, j) for j in range(1, n + 1)))
k = random.randint(0, 2 ** n - 2)
return list(islice(allcomb, k, k + 1))[0]
pickcomb(ascii_uppercase[:22])
('A', 'E', 'F', 'H', 'I', 'K', 'L', 'M', 'O', 'Q', 'S', 'T')
私は多数の上に、私たちはかなり均一な分布を見るべきであると思われるのは、
それをテストしてみましょう。 pandas.value_counts
を使用します。正確な観測タイプ数とかなり均一な分布を持っていることが分かります。
import pandas as pd
s = pd.value_counts([pickcomb(ascii_uppercase[:5]) for _ in range(100000)])
print(len(s), 2 ** 5 - 1, s, sep='\n\n')
31
31
(A, B, C, D, E) 3329
(A, D) 3320
(C, D) 3301
(A, D, E) 3277
(D, E) 3276
(B, C, D) 3270
(A, E) 3268
(A, B) 3258
(C, E) 3251
(A, B, C) 3250
(A, B, C, E) 3248
(C, D, E) 3245
(A, C) 3245
(D,) 3241
(C,) 3234
(A, B, D) 3227
(A, C, E) 3220
(B, D, E) 3215
(A, B, E) 3213
(B, C, E) 3213
(B, C, D, E) 3213
(A, C, D) 3211
(B, E) 3194
(B, C) 3193
(A, B, D, E) 3185
(A, B, C, D) 3174
(A, C, D, E) 3158
(E,) 3151
(B,) 3150
(B, D) 3148
(A,) 3122
dtype: int64
- 1. 配列から組み合わせを生成するには?
- 2. 与えられた範囲から組み合わせを生成
- 3. 整数の組み合わせをこれらの組み合わせの合計のリストに変換する
- 4. リスト[9,2,11] .Find Pythonで9211のような最大の組み合わせを考えると
- 5. 複数のリストからランダムにn個の組み合わせを作成する
- 6. 1つの色から色の組み合わせを生成
- 7. 同じ番号を使用する組み合わせを含む、リュージョンを使用してリストからすべての組み合わせを取得する
- 8. Pythonで定義済みのテンプレートから可能な組み合わせのリストを作成するには
- 9. シンボルの組み合わせはどのように生成されますか?
- 10. Python- 2つのリストを組み合わせてリストのリストを作成する
- 11. リスト内の要素からすべての組み合わせを生成するにはどうすればよいですか?例えば
- 12. Django、phonegapとheroku。それらをどのように組み合わせるか?
- 13. 各行にリストの組み合わせを作成するパンダ
- 14. Smalltalkのコレクションからすべての組み合わせを生成する
- 15. 辞書をPythonの同じキーと組み合わせるにはどうすればいいですか?
- 16. 同じ列に2行を組み合わせる
- 17. プロローグ(Sicstus) - SETOFとfindAllの組み合わせは、ルートのセット与えられた駅がある考える
- 18. Javaの組み合わせの生成
- 19. 考えられるすべての要素の組み合わせを列挙する方法
- 20. これらのxpath式はどのように組み合わせますか?
- 21. Python:完全な因数の組み合わせを生成するには?
- 22. ネストされた配列(JS)から一意の組み合わせを生成
- 23. この基準で考えられるすべての組み合わせを見つける方法は?
- 24. Python itertoolsの組み合わせの組み合わせ
- 25. 組み合わせ - 配列からの人をペアにする
- 26. Perlでは、リストのすべての組み合わせをどのように生成できますか?
- 27. この2つのテーブルをどのように組み合わせて同じ列にするのですか?
- 28. 2つのテーブルからランダムな組み合わせを受け取るクエリ
- 29. 同じ親でdivsを変数classNameと組み合わせるにはどうすればよいですか?
- 30. 与えられた名目との組み合わせの数
私はあなたが選ぶ要素数(n)と、それらの要素をピックアップするためにn個のランダムを実行する2つのランダム関数を実行する必要があると思います。 – Gui
'['a'、 'c']'は '['c'、 'a']'と異なっていますか? – piRSquared
@ piRSquared彼は組み合わせではなく、順列ではないと言った。 –