具有分组随机正态值的 R 模拟数据

R simulation data with grouped random normal values

我有一个数据集,其中包含大约 10k 个与产品及其价格相关的数据点。我想根据产品价格从遵循特定模式的正态分布生成模拟销售数据。例如,如果价格低,例如,少于 40 个销售额(数量)应该从均值 120 和 sd=20 的正态分布中提取。如果价格是平均价格,例如在 40 到 50 之间,则应从均值为 80 且 sd=15 的正态分布中提取数量。如果价格很高,例如高于 50,则应从平均值为 20 且 sd=3

的正态中提取数量

我创建了以下工作示例:

dt <- tibble(sample(x = c("cheap","mediumA", "mediumB", 
                      "mediumC", "expensive"),
   prob = c(.3, .2,.2,.2, .1), 
   size = 10000,
   replace = TRUE))
dt <- dt %>% 
  mutate(productName=`sample(...)`,
         Price=case_when(
           productName=="cheap"~10,
           productName=="mediumA"~40,
           productName=="mediumB"~45,
           productName=="mediumC"~50,
           TRUE~300)) %>% 
  select(productName, Price)

我尝试了以下方法,但它不起作用。

dt %>% count(Price)
dt <- dt %>% 
  mutate(
    Quantity=case_when(
  Price<40 ~ 
    rnorm(dt %>%
            filter(Price<40) %>% 
            count(Price) %>% 
            pull(n), 120, 20),
  Price >=40 & Price <= 50 ~ 
    rnorm(dt %>%
            filter(Price >=40 & 
                     Price <= 50) %>% 
            count(Price) %>%
            pull(n) %>% 
            sum(), 80, 15),
  TRUE~ 
    rnorm(dt %>%
            filter(Price>50) %>% 
            count(Price) %>% 
            pull(n), 20, 3)))

上述 R 脚本产生以下错误消息:

Error: 
Price < 40 ~ rnorm(dt %>% filter(Price < 40) %>% count(Price) %>%      pull(n), 120, 20), 
Price >= 40 & Price <= 50 ~ rnorm(dt %>% filter(Price >= 40 &      
Price <= 50) %>% count(Price) %>% pull(n) %>% sum(), 80,      15), 
TRUE ~ rnorm(dt %>% filter(Price > 50) %>% count(Price) %>% pull(n),      20, 3) 
must be length 1000 or one, not 313, 597, 90 Call rlang::last_error() to see a backtrace

任何关于如何使这项工作的建议都很好。

您可以使用 purrr 包中的 map 来实现您想要的结果,该包是 tidyverse:

的一部分
 fun <- function(p) {
   case_when(p < 40 ~ rnorm(1, 120, 20),
             p <= 50 ~ rnorm(1, 80, 15),
             p > 50 ~ rnorm(1, 20, 3))
 }
 
 dt %>%
   mutate(Quantity = map_dbl(Price, fun))

您可以使用嵌套 ifelse,但是,您需要计算范围内有多少个值(我们使用 sum 来计算)并在 [=13] 中一次性生成它们=].

library(dplyr)

dt %>% 
  mutate(Quantity= ifelse(Price < 40, rnorm(sum(Price < 40), 120, 20),
              ifelse(Price <= 50, rnorm(sum(Price >= 40 & Price < 50), 80, 12), 
                                  rnorm(sum(Price > 50), 20, 3))))