具有分组随机正态值的 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))))
我有一个数据集,其中包含大约 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))))