Как смоделировать доход с помощью испытаний Бернулли / вероятностей успеха в R?

Я хотел бы смоделировать сценарии доходов для: price и est_p (оценочная вероятность) из следующих df:

df <- data.frame(price        = c(200, 100, 600, 20, 100),
                 est_p        = c(0.9, 0.2, 0.8, 0.5, 0.6),
                 actual_sale  = c(FALSE, TRUE, TRUE, TRUE, TRUE))

Выручка - сумма price, где actual_sale равно TRUE:

print(actual1 <- sum(df$price[df$actual_sale])) # Actual Revenue

[1] 820

Я создал функцию для имитации испытаний Бернулли со значениями est_p и price:

bernoulli <- function(df) {
        sapply(seq(nrow(df)), function(x) {
                prc <- df$price[x]
                p   <- df$est_p[x]
                sample(c(prc, 0), size = 1000, replace = T, prob = c(p, 1 - p))
                })
}

И применил его к образцу df:

set.seed(100)
distr1 <- rowSums(bernoulli(df))
quantile(distr1)

  0%  25%  50%  75% 100% 
   0  700  820  920 1020 

Выглядит нормально, фактическое значение = медиана! Но когда я применяю ту же функцию к увеличенному (реплицированному в 1000 раз) образцу - df1000, фактический доход выходит за пределы смоделированных значений:

df1000 <- do.call("rbind", replicate(1000, df, simplify = FALSE))

print(actual2 <- sum(df1000$price[df1000$actual_sale])) 

[1] 820000

distr2 <- rowSums(bernoulli(df1000))
quantile(distr2)

    0%    25%    50%    75%   100% 
726780 744300 750050 754920 775800

Почему фактическая выручка выходит за рамки смоделированных значений? Где я сделал ошибку и как правильно решить эту проблему?


person Georgie Shimanovsky    schedule 25.08.2019    source источник
comment
Почему вы меняете начальные значения?   -  person deepseefan    schedule 26.08.2019
comment
Ну на всякий случай. Даже если бы я не стал, это не имеет значения для проблемы.   -  person Georgie Shimanovsky    schedule 26.08.2019
comment
Затем проверьте это, set.seed(100) и запустите distr1 <- rowSums(sim(df)), а затем quantile(distr1), измените начальное значение на 200 и снова запустите вышеуказанное, посмотрите результат, он даст вам другой результат. Идея затравки состоит в том, чтобы сделать воспроизводимую случайную выборку.   -  person deepseefan    schedule 26.08.2019
comment
Проблема в том, что доход выходит за рамки, независимо от того, установлен ли начальный результат 100 или 200. Это то, что я имел в виду.   -  person Georgie Shimanovsky    schedule 26.08.2019
comment
Мы придем к этому, если вы исправите константу семени.   -  person deepseefan    schedule 26.08.2019
comment
Я удалил второй set.seed для удобства и обновил вывод, но это не так, не могли бы вы проверить на своей стороне.   -  person Georgie Shimanovsky    schedule 26.08.2019
comment
Теперь измените rbind в вашем do.call на cbind и посмотрите, дает ли он вам то, что вы хотите.   -  person deepseefan    schedule 26.08.2019
comment
Похоже, вы не уловили проблему. Фактический доход для второго случая составляет 820000, поскольку размер выборки увеличивается в 1000 раз за счет репликации rbind.   -  person Georgie Shimanovsky    schedule 26.08.2019
comment
разве мы не говорим о binomial distributions (распределении вероятностей)? Почему реальная выручка по второму делу 820000?   -  person deepseefan    schedule 26.08.2019
comment
print (actual2 ‹- sum (df1000 $ price [df1000 $ sale])) Колонка продажи показывает фактический результат (ИСТИНА / ЛОЖЬ). Если у вас есть какие-либо мысли о том, как смоделировать распределение доходов на основе упомянутого выше, не могли бы вы поделиться ответом?   -  person Georgie Shimanovsky    schedule 26.08.2019
comment
Это опечатка или на самом деле Bernulli в названии или Bernoulli?   -  person deepseefan    schedule 26.08.2019
comment
Это. исправлено, спасибо   -  person Georgie Shimanovsky    schedule 26.08.2019
comment
Я как бы понял проблему с вашим текущим подходом. temp <- bernoulli(df1000). Вам нужно взять rowSums и quantile из каждых 5 столбцов, поскольку они составляют одну группу. Сделайте lapply(seq(1, ncol(temp), 5), function(x) quantile(rowSums(temp[, x:(x + 4)]))), и они следуют тому же распределению quantile.   -  person Ronak Shah    schedule 27.08.2019


Ответы (1)


Мне нужно было место, чтобы прояснить мой комментарий, в котором говорится, что измените rbind на cbind в вашем do.call. Вот он и почему я это сказал.

set.seed(100)
df <- data.frame(price        = c(200, 100, 600, 20, 100),
                 est_p        = c(0.9, 0.2, 0.8, 0.5, 0.6),
                 actual_sale  = c(FALSE, TRUE, TRUE, TRUE, TRUE))

print(actual1 <- sum(df$price[df$actual_sale])) # Actual Revenue

[1] 820

# here is where you need to change the rbind to cbind to stay within the range 
# otherwise you're essentially changing the distribution of the data and you 
# can't compare the results 
df1000 <- do.call("cbind", replicate(1000, df, simplify = FALSE))
print(actual2 <- sum(df1000$price[df1000$actual_sale])) 
[1] 820

Вот дистрибутив simulated, дистрибутив rbind и дистрибутив cbind для вашего наглядного представления. Как видите, simulated и cbind одинаковы. rbind произвел другое распределение. quantile() или fivenum() взяты из раздачи. Вот почему вы получаете другой номер.

binomial_out

Надеюсь, это поможет отследить причину, по которой или откуда quantile() получает числа.

person deepseefan    schedule 26.08.2019