Сгенерируйте столбец со случайным di git со средним значением = 20, максимумом = 25 и минимумом = 5 как можно быстрее в pandas - PullRequest
1 голос
/ 17 июня 2020

У меня есть df, как показано ниже

        df = pd.DataFrame({'Session': ['s1', 's1', 's1', 's1', 's1', 's1', 's1',
                                       's1', 's1', 's1', 's1', 's1', 's1', 's1', 's1'],
                          'slot_num': [1, 2, 3, 3, 4, 4, 5, 5, 6, 7, 7, 8, 8, 9, 9]})

df:

Session         slot_num
s1              1
s1              2
s1              3
s1              3
s1              4
s1              4
s1              5
s1              5
s1              6
s1              7
s1              7
s1              8
s1              8
s1              9
s1              9

Из приведенного выше я хотел бы создать столбец с именем service_time случайным образом со средним точно 20, максимум 25 и минимум 2. как можно быстрее.

Я пробовал приведенный ниже код, но он не дает точного среднего значения 20.

Примечание. Время обслуживания должно содержать только целые числа

# generate service time with mean = 20, min = 2 and max = 25
def gen_avg(n, expected_avg=20, a=2, b=25):
    l = np.random.randint(a, b, size=n)
    while True:
        if np.mean(l) == expected_avg:
            break
        while np.mean(l) > expected_avg:
            c = np.random.choice(np.where(l>expected_avg)[0])
            l[c] = np.random.randint(a, expected_avg+1)
        while np.mean(l) < expected_avg:
            c = np.random.choice(np.where(l<expected_avg)[0])
            l[c] = np.random.randint(expected_avg, b)
        return l

df['service_time'] = df.groupby('Session')['Session'].transform(lambda x: gen_avg(len(x)))

Я тоже пробовал и ниже, но это занимает очень много времени

#https://stackoverflow.com/a/39435600/2901002
def gen_avg(n, expected_avg=20, a=5, b=25):
    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)))

1 Ответ

1 голос
/ 17 июня 2020

Вероятно, это займет много времени, потому что вы ожидаете, что среднее значение будет точно равно expected_avg. Поскольку это случайная величина, в которой одно из n наблюдений может изменить среднее значение, это проблема, особенно когда n растет. Если это разрешено, вы можете использовать такой метод, чтобы среднее значение было достаточно близким, например, не более 5%. Предположим, мы называем это tolerance. Попробуйте что-то вроде следующего:

while abs((avg-expected_avg)/expected_avg) > tolerance:
  l = np.random.randint(a, b, size=n)
  avg = np.mean(l)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...