генерировать случайное число от 2 до 40 со средним значением 20 в виде столбца в pandas - PullRequest
1 голос
/ 23 апреля 2020

У меня есть фрейм данных, как показано ниже

session      slot_num     appt_time
s1           1            2020-01-06 09:00:00
s1           2            2020-01-06 09:20:00
s1           3            2020-01-06 09:40:00
s1           3            2020-01-06 09:40:00
s1           4            2020-01-06 10:00:00
s1           4            2020-01-06 10:00:00
s2           1            2020-01-06 08:20:00
s2           2            2020-01-06 08:40:00
s2           2            2020-01-06 08:40:00
s2           3            2020-01-06 09:00:00
s2           4            2020-01-06 09:20:00
s2           5            2020-01-06 09:40:00
s2           5            2020-01-06 09:40:00
s2           6            2020-01-06 10:00:00
s3           1            2020-01-09 13:00:00
s3           1            2020-01-09 13:00:00
s3           2            2020-01-09 13:20:00
s3           3            2020-01-09 13:40:00

В приведенном выше примере я хотел бы добавить столбец с именем service_time.

service_time должен содержать любые случайные цифры от 2 до 40 со средним значением 20 для каждого сеанса.

Я предпочитаю, чтобы случайные числа следовали случайному нормальному распределению со средним 20, стандартным отклонением 10, минимальным 2 и максимальным 40

Ожидаемый результат:

session      slot_num     appt_time               service_time
s1           1            2020-01-06 09:00:00     30
s1           2            2020-01-06 09:20:00     10
s1           3            2020-01-06 09:40:00     15
s1           3            2020-01-06 09:40:00     35
s1           4            2020-01-06 10:00:00     20
s1           4            2020-01-06 10:00:00     10
s2           1            2020-01-06 08:20:00     15
s2           2            2020-01-06 08:40:00     20
s2           2            2020-01-06 08:40:00     25
s2           3            2020-01-06 09:00:00     30
s2           4            2020-01-06 09:20:00     20
s2           5            2020-01-06 09:40:00     8
s2           5            2020-01-06 09:40:00     40
s2           6            2020-01-06 10:00:00     2
s3           1            2020-01-09 13:00:00     4
s3           1            2020-01-09 13:00:00     32
s3           2            2020-01-09 13:20:00     26
s3           3            2020-01-09 13:40:00     18

Примечание: обратите внимание, что это та случайная комбинация, которая соответствует минимальным, максимальным и средним критериям, указанным выше.

Ответы [ 3 ]

1 голос
/ 23 апреля 2020

Вот решение с новой инфраструктурой генератора NumPy. См. документацию для обсуждения различий между этой и более старой инфраструктурой RandomState.

import numpy as np
from numpy.random import default_rng

# assuming df is the name of your dataframe
n = len(df)

# set up random number generator
rng = default_rng()

# sample more than enough values
vals = rng.normal(loc=20., scale=10., size=2*n)

# filter values according to cut-off conditions
vals = vals[2 <= vals]
vals = vals[vals <= 40]

# add n random values to dataframe
df['service_time'] = vals[:n]
1 голос
/ 23 апреля 2020

Нормальное распределение имеет неограниченный диапазон, поэтому, если вы ограничиваетесь между 2 и 40, распределение не является нормальным. Альтернативой, которая ограничена и избегает схем принятия / отклонения, является использование tri angular дистрибутива (, см. Википедию для деталей ). Поскольку среднее значение для распределения angular равно (left + mode + right) / 3, с left = 2 и right = 40, вы должны установить mode = 18, чтобы получить желаемое среднее значение 20.

1 голос
/ 23 апреля 2020

Одно возможное решение с функцией Cutom:

#https://stackoverflow.com/a/39435600/2901002
def gen_avg(n, expected_avg=20, a=2, b=40):
    while True:
        l = np.random.randint(a, b, size=n)
        avg = np.mean(l)

        if avg == expected_avg:
            return l

df['service_time'] = df.groupby('session')['session'].transform(lambda x: gen_avg(len(x)))
print (df)
   session  slot_num            appt_time  service_time
0       s1         1  2020-01-06 09:00:00            31
1       s1         2  2020-01-06 09:20:00             9
2       s1         3  2020-01-06 09:40:00            23
3       s1         3  2020-01-06 09:40:00            37
4       s1         4  2020-01-06 10:00:00             6
5       s1         4  2020-01-06 10:00:00            14
6       s2         1  2020-01-06 08:20:00            33
7       s2         2  2020-01-06 08:40:00            29
8       s2         2  2020-01-06 08:40:00            18
9       s2         3  2020-01-06 09:00:00            32
10      s2         4  2020-01-06 09:20:00             9
11      s2         5  2020-01-06 09:40:00            26
12      s2         5  2020-01-06 09:40:00            10
13      s2         6  2020-01-06 10:00:00             3
14      s3         1  2020-01-09 13:00:00            19
15      s3         1  2020-01-09 13:00:00            22
16      s3         2  2020-01-09 13:20:00             5
17      s3         3  2020-01-09 13:40:00            34
...