循环数据帧以模拟正常的数据分布
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
包含基于同一行中的 observations
、average
和 variance
的模拟数据列表。您现在可以使用例如
提取此列表
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>
我想遍历包含数据模拟参数的数据帧。理想情况下,我可以避免为此编写 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
包含基于同一行中的 observations
、average
和 variance
的模拟数据列表。您现在可以使用例如
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>