什么是生成從 0 到 50、大小為 1000 的亂數的最簡潔方法,條件是任何數字都不應與使用 python 和 numpy 的任何其他數字具有相同的出現次數。
大小 10 的示例:[0, 0, 0, 1, 1, 3, 3, 3, 3, 2] --> 沒有數字出現相同的次數
uj5u.com熱心網友回復:
從rng.dirichlet分布中抽取樣本并拒絕樣本可確保滿足要求,但唯一元素數量的熵較低。您必須自己調整獨特元素的范圍np.ones(rng.integers(min,max))。如果max接近唯一元素的最大數量(此處為 50),則拒絕可能需要很長時間或沒有解決方案,從而導致無限回圈。該代碼用于生成大小為 100 的陣列。
import numpy as np
times = np.array([])
rng = np.random.default_rng()
#rejection sampling
while times.sum() != 100 or len(times) != len(np.unique(times)):
times = np.around(rng.dirichlet(np.ones(rng.integers(5,10)))*100)
nr = rng.permutation(np.arange(51))[:len(times)]
np.repeat(nr, times.astype(int))
隨機輸出
array([ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 33, 33, 33,
33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 25, 5, 5, 5])
uj5u.com熱心網友回復:
為了避免在可能很長的試錯回圈中生成隨機磁區的可變性,您可以使用一個函式直接生成一個數字的隨機磁區,其中所有部分都是不同的(增加)。從那里你只需要在磁區函式提供的塊上映射洗牌的數字:
def randPart(N,size=0): # O(√N)
if not size:
maxSize = int((N*2 0.25)**0.5-0.5) # ∑1..maxSize <= N
size = random.randrange(1,maxSize) # select random size
if size == 1: return (N,) # one part --> all of N
s = size*(size-1)//2 # min sum of deltas for rest
a = random.randrange(1,(N-s)//size) # base value
p = randPart(N-a*size,size-1) # deltas on other parts
return (a,*(n a for n in p)) # combine to distinct parts
用法:
size = 30
n = 10
chunks = randPart(size)
numbers = random.sample(range(n),len(chunks))
result = [n for count,n in zip(chunks,numbers) for _ in range(count)]
print(result)
[9, 9, 9, 0, 0, 0, 0, 7, 7, 7, 7, 7, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6]
# resulting frequency counts
from collections import Counter
print(sorted(Counter(result).values()))
[3, 4, 5, 6, 12]
請注意,如果您的亂數范圍小于不同磁區的最大數量(例如,對于 1000 個值的輸出少于 44 個數字),您需要修改 randPart 函式以在其計算中考慮限制最大尺寸:
def randPart(N,sizeLimit=0,size=0):
if not size:
maxSize = int((N*2 0.25)**0.5-0.5) # ∑1..maxSize <= N
maxSize = min(maxSize,sizeLimit or maxSize)
...
您也可以更改它以強制最小數量的磁區
uj5u.com熱心網友回復:
這以@MYousefi 建議的方式解決了您的問題。
import random
seq = list(range(50))
random.shuffle(seq)
values = []
for n,v in enumerate(seq):
values.extend( [v]*(n 1) )
if len(values) > 1000:
break
print(values)
請注意,您無法準確獲得 1,000 個數字。起初,我生成了整個序列,然后取了前 1,000 個,但這意味著無論哪個序列被截斷,都將與之前的序列長度相同。你最終得到 1,035。
uj5u.com熱心網友回復:
這是產生所需輸出的遞回且可能非常慢的實作。
import numpy as np
def get_sequence_lengths(values, total):
if total == 0:
return [[]], True
if total < 0:
return [], False
if len(values) == 0:
return [], False
sequences = []
result = False
for i in range(len(values)):
ls, suc = get_sequence_lengths(values[:i] values[i 1:], total - values[i])
result |= suc
if suc:
sequences.extend([[values[i]] s for s in ls])
return sequences, result
def gen_numbers(rand_min, rand_max, count):
values = list(range(rand_min, rand_max 1))
sequences, success = get_sequence_lengths(list(range(1, count 1)), count)
sequences = list(filter(lambda x: len(x) <= 1 rand_max - rand_min, sequences))
if not success or not len(sequences):
raise ValueError('Cannot generate with given parameters.')
sequence = sequences[np.random.randint(len(sequences))]
values = np.random.choice(values, len(sequence), replace=False)
result = []
for v, s in zip(values, sequence):
result.extend([v] * s)
return result
get_sequence_length將生成總和為給定總數的唯一正整數的所有排列。然后將通過可用值的數量進一步過濾該序列。最后,從序列中生成配對值和計數產生輸出。
如上所述get_sequence_length是遞回的,并且對于較大的輸入值將非常慢。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/416469.html
標籤:
上一篇:行和列索引之間具有絕對差異的矩陣
下一篇:根據條件替換大塊numpy陣列
