循环数据帧以模拟正常的数据分布

loop over dataframe to simulate normal data distrbution

我想遍历包含数据模拟参数的数据帧。理想情况下,我可以避免为此编写 for loop 并在 tidyverse 中进行,但我还没有找到可行的解决方案。

考虑一个带有参数的数据框:

grouping1 <- c('a','a', 'a', 'b', 'b', 'b')
grouping2 <- c('A','A', 'B', 'B', 'C', 'C')
grouping3 <- c('1','2', '3', '4', '5', '6')
observations <- c(14, 14, 12, 12, 15, 15)
average <- c(334, 336, 243, 645, 233, 625)
variance <- c(2, 6, 7, 9, 2, 6)
my_data <- cbind(grouping1,grouping2,grouping3,observations,average,variance)

以及基于这些参数模拟值的简单管道:

my_generated_data <- my_data %>%
  group_by(grouping1,grouping2,grouping3) %>%
  rnorm(n=observations, mean=average, sd=variance) 

但这不起作用。一方面,我收到有关未使用的“。”的错误消息。参数,但以下内容也不起作用:

my_generated_data <- my_data %>%
  group_by(grouping1,grouping2,grouping3) %>%
  rnorm(n=.$observations, mean=.$average, sd=.$variance) 

另一个问题是生成的观察值数量因分组级别(例如 12、14 或 15)而异。这不应该是一个主要问题,但它确实意味着生成的数据帧必须很长,而不是考虑到不均匀的行数。预先感谢您的帮助。

第一个问题是您要将向量组合成矩阵。结果矩阵的类型是 character,因为至少有一个向量是 character。您需要存储保留其类型的向量的类型是 data.frame,如

my_data <- data.frame(grouping1 = grouping1,
                      grouping2 = grouping2,
                      grouping3 = grouping3,
                      observations = observations,
                      average = average,
                      variance = variance, 
                      stringsAsFactors = FALSE)

现在,您可以遍历数据框的行并模拟您的数据。由于模拟的长度取决于您提到的 observation 列,因此创建观察列表:

simulationList <- lapply(1:NROW(my_data), function(k) {
  rnorm(n = my_data$observations[k], mean = my_data$average[k], sd = sqrt(my_data$variance[k])) 
})

您现在想要将模拟添加到您的数据框中。这是否是个好主意,是你的责任。但是您可以通过将数据框扩展(复制)到合适的长度并添加类似

的模拟来实现这一点
my_data <- my_data[rep(1:NROW(my_data), times = my_data$observations),]
my_data$simulation <- unlist(simulationList)

Joans 已经回答了这个问题,但我想使用 tidyverse.

添加一个解决方案

首先,R >= 4.0,定义data.frames时不需要stringsAsFactors参数。 my_data的定义就是

my_data <- data.frame(grouping1,grouping2,grouping3,observations,average,variance)

现在我们可以使用

library(dplyr)

my_generated_data <- my_data %>% 
  group_by(grouping1, grouping2, grouping3) %>% 
  mutate(sim = list(rnorm(n = observations, mean = average, sd = sqrt(variance))))

获得

# Groups:   grouping1, grouping2, grouping3 [6]
  grouping1 grouping2 grouping3 observations average variance sim       
  <chr>     <chr>     <chr>            <dbl>   <dbl>    <dbl> <list>    
1 a         A         1                   14     334        2 <dbl [14]>
2 a         A         2                   14     336        6 <dbl [14]>
3 a         B         3                   12     243        7 <dbl [12]>
4 b         B         4                   12     645        9 <dbl [12]>
5 b         C         5                   15     233        2 <dbl [15]>
6 b         C         6                   15     625        6 <dbl [15]>

其中列 sim 包含基于同一行中的 observationsaveragevariance 的模拟数据列表。您现在可以使用例如

提取此列表
my_generated_list[[1, "sim]]
#> [[1]]
#> [1] 333.9635 335.0959 334.2201 335.6582 335.0773 335.6701 331.9570 334.0041 332.9627 333.5582 335.6228 334.4168 330.4192
#> [14] 335.2726

unnest

my_data %>% 
  group_by(grouping1, grouping2, grouping3) %>% 
  mutate(sim = list(rnorm(n = observations, mean = average, sd = sqrt(variance)))) %>% 
  unnest_wider(sim) # use unnest(sim) or unnest_longer(sim) for a "long" format

回归

# A tibble: 6 x 21
# Groups:   grouping1, grouping2, grouping3 [6]
  grouping1 grouping2 grouping3 observations average variance  ...1  ...2  ...3  ...4  ...5  ...6  ...7  ...8  ...9 ...10
  <chr>     <chr>     <chr>            <dbl>   <dbl>    <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 a         A         1                   14     334        2  334.  333.  337.  335.  332.  334.  335.  334.  335.  333.
2 a         A         2                   14     336        6  338.  336.  333.  334.  334.  336.  333.  339.  336.  335.
3 a         B         3                   12     243        7  243.  244.  243.  241.  241.  250.  243.  239.  243.  240.
4 b         B         4                   12     645        9  645.  645.  647.  641.  648.  639.  650.  647.  643.  641.
5 b         C         5                   15     233        2  232.  234.  235.  237.  233.  232.  235.  231.  233.  236.
6 b         C         6                   15     625        6  621.  625.  632.  625.  626.  626.  623.  620.  627.  630.
# ... with 5 more variables: ...11 <dbl>, ...12 <dbl>, ...13 <dbl>, ...14 <dbl>, ...15 <dbl>