Как сделать нормальное распределение python

Рейтинг: -1Ответов: 3Опубликовано: 13.06.2023

У меня есть, допустим, 400 человек. Нужно их нормальным образом распределить на 12 отрезков времени. Каким способом можно это сделать с помощью python? Чтобы сумма распределенного массива в итоге была 400. (среднее и нормальное отклонение рандомно)

n = 400

итоговый список должен быть типа такого

itog = [1,7, 20, .., 75, ..., 22, 6, 2]

Ответы

▲ 2Принят
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

labels = pd.date_range("11:00", "12:00", freq="5T").strftime("%H:%M")

fig, ax = plt.subplots()
n, bins, patches = ax.hist(np.random.default_rng().normal(loc=0.0, scale=.1, size=400), bins=12)
ax.set_xticks(bins, labels = labels)
plt.bar_label(patches)

plt.xticks(rotation=45)
plt.show()

введите сюда описание изображения

▲ 0

Можно просто через random.gauss сгенерировать 400 случайных чисел, и разложить их на 12 ячеек:

from collections import defaultdict
import random

# Сигма 1.5 подобрана так, чтобы случайные числа доходили
# до границ интервала от 0 до 12, но более-менее оставались в нем
items = [random.gauss(6, 1.5) for i in range(400)]  

print(min(items), max(items))

buckets = defaultdict(int)
for item in items:
    bucket_index = int(item)
    if bucket_index < 0:
        bucket_index = 0
    elif bucket_index > 11:
        bucket_index = 11
    buckets[bucket_index] += 1

print(buckets)

result = [buckets[i] for i in range(12)]

print(result)
print(sum(result))

Вывод:

1.6125542288793255 11.389099737688543
defaultdict(<class 'int'>, {6: 107, 8: 25, 4: 63, 5: 97, 7: 51, 3: 45, 10: 3, 2: 3, 1: 1, 9: 4, 11: 1})
[0, 1, 3, 45, 63, 97, 107, 51, 25, 4, 3, 1]
400

Вместо подбора сигмы, можно взять максимальное и минимальное значение, разбить фактический интервал на 12 равных отрезков, и считать попадание в каждый отрезок. Но это немного усложнит проверку попадания в отрезки (придется делать настоящее сравнение с границами отрезков вместо округления до целого).

▲ 0

В моём варианте генерируется 400 случайных чисел в диапазоне от 0 до количества интервалов. Если случайное число оказалось за пределами диапазона, то оно отбрасывается, и генерируется новое число. А затем подсчитывается количество чисел, соответствующих каждому интервалу.

import numpy as np
import matplotlib.pyplot as plt

N = 400
timeInterval = 0.05
intervalsCount = 12
mean = np.random.randint(10, 20)
stddev = np.random.uniform(0.5, 5)

dist = []
i = 0
while i < N:
  cur = np.random.normal(intervalsCount / 2, stddev)
  if cur >= 0 and cur < intervalsCount:
    dist.append(int(cur))
    i += 1
dist = np.array(dist)

intervals = [i for i in np.arange(mean - timeInterval * intervalsCount / 2, mean + timeInterval * intervalsCount / 2, timeInterval)]
intervDict = {f'{t1:.2f}-{t2:.2f}': np.count_nonzero(dist==num) for num, (t1, t2) in enumerate(zip(intervals, intervals[1:]))}



s = sum(intervDict.values())
print(intervDict)
print(s)
plt.plot(intervDict.keys(), intervDict.values())

Вывод:

{'16.70-16.75': 7, '16.75-16.80': 16, '16.80-16.85': 29, '16.85-16.90': 48, '16.90-16.95': 43, '16.95-17.00': 58, '17.00-17.05': 59, '17.05-17.10': 53, '17.10-17.15': 34, '17.15-17.20': 31, '17.20-17.25': 16, '17.25-17.30': 6}
400