R中按行模拟
Simulations by row in R
我正在尝试通过模拟使用分位数获得 90% 的区间。我有一个数据集,其中每一行包含平均值、标准差和模拟次数 运行。
当我尝试 运行 代码时,出于某种原因,它只为整个数据集创建分位数,而不是将每行中包含的信息用作模拟参数。有什么方法可以让它在每一行都起作用吗?
这是我正在使用的示例:
avg <- c(24, 20, 29, 17, 22, 21)
sd <- c(5, 4, 5, 3, 3, 3.6)
sims <- 1000
df <- data.frame(avg, sd, sims)
df$Low90 <- round(quantile(rnorm(n = sims, mean = df$avg, sd = df$sd), prob = 0.05), 2)
df$High90 <- round(quantile(rnorm(n = sims, mean = df$avg, sd = df$sd), prob = 0.95), 2)
df
avg sd sims Low90 High90
1 24 5.0 1000 14.13 32.32
2 20 4.0 1000 14.13 32.32
3 29 5.0 1000 14.13 32.32
4 17 3.0 1000 14.13 32.32
5 22 3.0 1000 14.13 32.32
6 21 3.6 1000 14.13 32.32
使用apply
,
df$Low90 <- apply(df, 1, function(x) round(quantile(rnorm(n = x[3], mean = x[1], sd = x[2]), prob = 0.05), 2))
df$High90 <- apply(df, 1, function(x) round(quantile(rnorm(n = x[3], mean = x[1], sd = x[2]), prob = 0.95), 2))
df
avg sd sims Low90 High90
1 24 5.0 1000 16.08 32.08
2 20 4.0 1000 13.65 26.78
3 29 5.0 1000 20.55 36.96
4 17 3.0 1000 11.94 22.26
5 22 3.0 1000 17.13 26.95
6 21 3.6 1000 14.79 26.84
我们正在做的是使用 apply
函数,边距为 1,这意味着逐行。然后在每一行中,我们得到 means
、sd
和 simulation
数字,并通过模拟函数得到 运行。
dplyr
解决方案将使用 rowwise
函数,
library(dplyr)
df %>% rowwise %>%
mutate(Low90 = round(quantile(rnorm(n = sims, mean = avg, sd = sd), prob = 0.05), 2))
这是一个使用 pmap
的 tidyverse
方法,因此对于任意数量的分位数,您只需要遍历行一次。您原始方法中的问题是 rnorm
未对其 n
参数进行矢量化;尝试 运行 rnorm(n = sims, mean = df$avg, sd = df$sd)
并注意你只得到一组 1000 个值。
在这里,我们将使用 pmap
遍历行,应用一个自定义函数,该函数采用与 probs
参数中一样多的分位数。我们需要使用 enframe
和 spread
来制作这些分位数而不是数字向量,以便 unnest
将所有内容保持在同一行。优点是现在如果你想要,比如说,每个百分位数,你可以只改变 probs
向量并获得 100 个新列。
avg <- c(24, 20, 29, 17, 22, 21)
sd <- c(5, 4, 5, 3, 3, 3.6)
sims <- 1000
df <- data.frame(avg, sd, sims)
library(tidyverse)
probs <- c(0.05, 0.5, 0.95)
quantile_tbl <- function(sims, avg, sd, probs) {
rnorm(sims, avg, sd) %>%
quantile(probs) %>%
round(2) %>%
enframe() %>%
spread(name, value)
}
df %>%
mutate(quantiles = pmap(select(., sims, avg, sd), ~quantile_tbl(..1, ..2, ..3, probs))) %>%
unnest()
#> avg sd sims 5% 50% 95%
#> 1 24 5.0 1000 15.96 24.04 32.42
#> 2 20 4.0 1000 13.53 20.17 26.72
#> 3 29 5.0 1000 20.59 29.13 37.27
#> 4 17 3.0 1000 11.83 17.08 21.76
#> 5 22 3.0 1000 16.75 22.05 27.17
#> 6 21 3.6 1000 14.87 20.79 26.94
由 reprex package (v0.2.1)
于 2019-04-24 创建
我正在尝试通过模拟使用分位数获得 90% 的区间。我有一个数据集,其中每一行包含平均值、标准差和模拟次数 运行。
当我尝试 运行 代码时,出于某种原因,它只为整个数据集创建分位数,而不是将每行中包含的信息用作模拟参数。有什么方法可以让它在每一行都起作用吗?
这是我正在使用的示例:
avg <- c(24, 20, 29, 17, 22, 21)
sd <- c(5, 4, 5, 3, 3, 3.6)
sims <- 1000
df <- data.frame(avg, sd, sims)
df$Low90 <- round(quantile(rnorm(n = sims, mean = df$avg, sd = df$sd), prob = 0.05), 2)
df$High90 <- round(quantile(rnorm(n = sims, mean = df$avg, sd = df$sd), prob = 0.95), 2)
df
avg sd sims Low90 High90
1 24 5.0 1000 14.13 32.32
2 20 4.0 1000 14.13 32.32
3 29 5.0 1000 14.13 32.32
4 17 3.0 1000 14.13 32.32
5 22 3.0 1000 14.13 32.32
6 21 3.6 1000 14.13 32.32
使用apply
,
df$Low90 <- apply(df, 1, function(x) round(quantile(rnorm(n = x[3], mean = x[1], sd = x[2]), prob = 0.05), 2))
df$High90 <- apply(df, 1, function(x) round(quantile(rnorm(n = x[3], mean = x[1], sd = x[2]), prob = 0.95), 2))
df
avg sd sims Low90 High90
1 24 5.0 1000 16.08 32.08
2 20 4.0 1000 13.65 26.78
3 29 5.0 1000 20.55 36.96
4 17 3.0 1000 11.94 22.26
5 22 3.0 1000 17.13 26.95
6 21 3.6 1000 14.79 26.84
我们正在做的是使用 apply
函数,边距为 1,这意味着逐行。然后在每一行中,我们得到 means
、sd
和 simulation
数字,并通过模拟函数得到 运行。
dplyr
解决方案将使用 rowwise
函数,
library(dplyr)
df %>% rowwise %>%
mutate(Low90 = round(quantile(rnorm(n = sims, mean = avg, sd = sd), prob = 0.05), 2))
这是一个使用 pmap
的 tidyverse
方法,因此对于任意数量的分位数,您只需要遍历行一次。您原始方法中的问题是 rnorm
未对其 n
参数进行矢量化;尝试 运行 rnorm(n = sims, mean = df$avg, sd = df$sd)
并注意你只得到一组 1000 个值。
在这里,我们将使用 pmap
遍历行,应用一个自定义函数,该函数采用与 probs
参数中一样多的分位数。我们需要使用 enframe
和 spread
来制作这些分位数而不是数字向量,以便 unnest
将所有内容保持在同一行。优点是现在如果你想要,比如说,每个百分位数,你可以只改变 probs
向量并获得 100 个新列。
avg <- c(24, 20, 29, 17, 22, 21)
sd <- c(5, 4, 5, 3, 3, 3.6)
sims <- 1000
df <- data.frame(avg, sd, sims)
library(tidyverse)
probs <- c(0.05, 0.5, 0.95)
quantile_tbl <- function(sims, avg, sd, probs) {
rnorm(sims, avg, sd) %>%
quantile(probs) %>%
round(2) %>%
enframe() %>%
spread(name, value)
}
df %>%
mutate(quantiles = pmap(select(., sims, avg, sd), ~quantile_tbl(..1, ..2, ..3, probs))) %>%
unnest()
#> avg sd sims 5% 50% 95%
#> 1 24 5.0 1000 15.96 24.04 32.42
#> 2 20 4.0 1000 13.53 20.17 26.72
#> 3 29 5.0 1000 20.59 29.13 37.27
#> 4 17 3.0 1000 11.83 17.08 21.76
#> 5 22 3.0 1000 16.75 22.05 27.17
#> 6 21 3.6 1000 14.87 20.79 26.94
由 reprex package (v0.2.1)
于 2019-04-24 创建