случайная выборка n цифр из диапазона (x, y), что в среднем означает k? - PullRequest
0 голосов
/ 07 ноября 2018

Я пытаюсь случайным образом выбрать n = 15 цифр из диапазона (низкий = 3, высокий = 7), чтобы при суммировании 15 выбранных цифр они составляли в среднем 5.

До сих пор мне удавалось только случайным образом выбрать n цифр из определенного диапазона, например:

n = 15
low  = 3
high = 8
range=[i for i in range(low,high)]
list =np.random.choice(range, n)

Это генерирует случайные 15 цифр целых чисел в диапазоне от 3, 4, 5, 6, 7. Тем не менее, я хочу, чтобы он выбирался случайным образом, но полученное среднее из n цифр равно 5? Как я могу пойти по этому поводу?

Ответы [ 3 ]

0 голосов
/ 07 ноября 2018

Я не уверен, что это соответствует вашим потребностям, но это один из способов сделать это.

import random

def kind_of_random(low, high, k, n):
    """
    Generate a list of n numbers between low and high
    with a mean of exactly k.
    """  
    assert k < high
    values = [low] * n
    to_add = (k - low) * n
    for _ in range(to_add):
        i = random.randint(0, n-1)
        # Don't want to add to a value that's already the max
        while values[i] == high:
            i = random.randint(0, n-1)
        values[i] += 1
    return values

ns = kind_of_random(3, 7, 5, 15)

Я уверен, что есть более эффективные варианты этой идеи - я думаю, что вы могли бы сделать это быстрее, запустив n * [k] вместо n * [low] и выполнив некоторое количество парных операций добавления / вычитания, но этого должно быть достаточно для маленьких n.

0 голосов
/ 07 ноября 2018

Ну, мы могли бы использовать распределение, результат которого естественно суммирует с известным значением, и с фиксированным числом выбранных чисел также будет означать среднее. Среднее значение 5 и число выборок, равное 15, означают, что общая сумма числа всегда должна быть равна 75.

Простейшим является Мультивыбор , поэтому давайте использовать его из NumPy. Мы устанавливаем равные вероятности на 1/15, выборка в диапазоне [0 ... 30] и отклоняем выборку, если какие-либо значения находятся выше желаемого диапазона.

Это быстрее, чем метод, предложенный @jbch, нет ручного баланса сумм и средних, и гистограмма распределения ближе к симметричной, если вы заботитесь об этом

код

import numpy as np

def multiSum(n, p, maxv):
    while True:
        v  = np.random.multinomial(n, p, size=1)
        q  = v[0]
        a,  = np.where(q > maxv) # are there any values above max
        if len(a) == 0: # accept only samples below or equal to maxv
            return q

N = 15
p = np.full((N), 1.0/np.float64(N))

mean  = 5
start = 3
stop  = 7
n = N*mean - N*start

h = np.zeros((5), dtype=np.int64)
print(h)
for k in range(0, 10000):
    ns = multiSum(n, p, stop-start) + start # result in [3...7]
    #print(np.mean(ns))
    for v in ns:
        h[v-start] += 1

print(h)

Типичная выходная гистограмма на моем компьютере

[15698 38107 44584 33719 17892]

@ jbch выходная гистограмма

[17239 39237 42188 28957 22379]
0 голосов
/ 07 ноября 2018

То, что вы хотите, кажется противоречием. Но есть способ получить результат, который, казалось бы, работает так, как вы хотите.

Вместо создания всего 15 случайных цифр в диапазоне, создайте еще больше. Может быть, пару тысяч. Убедитесь, что вы выбрали диапазон, где среднее значение должно быть примерно таким, как вы хотите, если числа были действительно случайными. Затем возьмите 15 чисел за раз и бросьте их в список. Выбросьте любые номера хвостов, которые не вписываются в группу из 15.

Теперь, просмотрите список и отбросьте каждый элемент, который не усредняется до нужного вам числа. Теперь у вас есть новый список только с группами чисел, которые должны усредняться так, как вы хотите, и все они должны быть псевдослучайными (или достаточно случайными). Поскольку у вас был такой большой пул чисел, этот список не должен быть пустым, если только вы не выбрали свой начальный диапазон очень плохо.

Создайте новое случайное число, которое будет индексом в списке, из которого вы будете объявлять свою окончательную группу чисел. Надеюсь, что это имеет смысл!

...