4 votes

Générateur de nombres aléatoires en Python lorsque la moyenne est connue

En Python, j'essaie d'obtenir une liste de 10 nombres aléatoires entre [0,100] qui ont une moyenne de 25. Toutes les informations dont je dispose sont ci-dessous.

Total = 250
Number_of_users = 10
Average_score = 25

Dans le passé, j'ai utilisé la fonction gaussienne dans random mais sans l'écart type, je suis un peu coincé. Est-ce qu'il y a une autre façon de faire ?

Mon résultat serait quelque chose comme :

[20, 30, 18, 21, 27, 30, 15, 24, 31, 30]

2voto

Severin Pappadeux Points 4093

Eh bien, si vous voulez if possible the total would be 250 as well La réponse serait alors un échantillonnage à partir de Distribution multinomiale . Par définition, il produira des valeurs aléatoires dont la somme est égale à 250 et la moyenne à 25. Si l'un des nombres est supérieur à 100 (ce qui serait assez rare), nous jouerons le jeu de l'acceptation/refus. Avec l'aide de NumPy

import numpy as np

Total = 250
Number_of_users = 10
Average_score = 25
Upper_boundary = 100

probs = np.full(10, 1.0/np.float64(Number_of_users), dtype=np.float64) # probabilities

N = 10000 # samples to test
k = 0
while k < N:
    q = np.random.multinomial(Total, probs)
    t = np.where(q > Upper_boundary) # check for out-of boundaries
    if np.any(t):
        print("Rejected, out of boundaries") # reject, do another sample
        continue
    # accepted
    # do something with q, print((sum(q), len(q), np.mean(q)))

    k += 1

1voto

Yu Zhang Points 1348

J'ai une idée :

import random

Number_of_users = 10
Average_score = 25

index = Number_of_users / 2
result = []

while index:
    index -= 1
    random_number = random.randint(0,51)
    result.append(random_number)
    result.append(50-random_number)

print (result)
print (sum(result))

Vous obtiendrez 5 paires de nombres aléatoires ; pour chaque paire de nombres aléatoires, le premier est généré aléatoirement entre 0~50, tandis que le second dépend du premier nombre.

L'inconvénient de mon approche est qu'elle ne prend pas en charge les nombres aléatoires impairs.

1voto

behold Points 207

Voici les 2 contraintes :

  1. Les numéros sont aléatoires

  2. La moyenne converge vers 25

Puisqu'il n'y a pas de contrainte sur les distributions, une façon d'y parvenir est d'échantillonner à partir de deux distributions uniformes différentes :

import random
out_list = []
for i in range(1,10):
    random_number = random.uniform(0,1)
    if random_number < 0.75:
        # Append uniform random number between 0 - 25 with probability .75
        out_list.append(random.randint(0,25))
    else:
        #Append uniform random number between 0-75 with probability 0.25
        out_list.append(random.randint(25,100))

print(out_list)
import statistics
print(statistics.mean(out_list))

Par ailleurs, cette question pourrait trouver un meilleur accueil sur stats.stackexchange.com.

0voto

BigH Points 193

Vous pouvez essayer une distribution bêta avec une valeur moyenne de 25, c'est-à-dire choisir des paramètres a,b tels que a/(a+b)=0,25. Le graphique ci-dessous donne une idée de la variance souhaitée en faisant varier les paramètres a et b. enter image description here

from scipy.stats import beta
import matplotlib.pyplot as plt
import numpy as np

fig, ax = plt.subplots(3, sharex=True, figsize=(7,7))

x = np.linspace(0,1,100)
a = [ 2.5,10, 25]
b = [ 7.5,30, 75]

for i in range(len(ax)):
    ax[i].plot(x,beta.pdf(x,a[i],b[i]))
    ax[i].text(0.75,0.75,"a={}, b={}".format(a[i],b[i]), transform=ax[i].transAxes)

plt.show()
result = list(map(int, 100*beta.rvs(10,30,size=9))) #to be more precise, need to check that these 9 values fall below 250
result.append(250-sum(result))
print("10 samples from a Beta(10,30) distribution:\n ",*result)

Out: 10 samples from a Beta(10,30) distribution:
  20 25 21 20 31 28 24 29 23 29

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X