简体   繁体   English

dplyr,purrr 或类似的过程来替换 R 中的 for 循环

[英]dplyr, purrr or similar process to replace for loop in R

I have a distribution of groups with a given number of individuals;我有一个给定数量的群体分布; for example: {2, 4, 1, 1, 2, 3}, where Group 1 has 2 individuals, Group 2 has 4 individuals, Group 3 has 1, Group 4 has 1, etc. I want to build a table where there is a unique row for each Group/Individual combination.例如:{2, 4, 1, 1, 2, 3},其中第 1 组有 2 个人,第 2 组有 4 个人,第 3 组有 1 人,第 4 组有 1 人,等等。我想在那里建一个表是每个组/个人组合的唯一行。 (Desired table format at the bottom of the question). (问题底部的所需表格格式)。

I currently use a for loop:我目前使用 for 循环:

num.groups <- 10
mu <- 4
sd <- 1

group.dist <- round(rnorm(num.groups, mean = mu, sd = sd))

xx <- NULL
for (i in 1:length(group.dist)) {
  temp <- data.frame(Group = i, Individual = 1:group.dist[i])
  xx <- rbind(xx, temp)
}

I'm trying to get away from using for loops in general, and the actual version of my code has hundreds of groups and I will be running a simulation thousands of times, so I'm hoping there is a more efficient method of doing this.我试图摆脱一般的 for 循环,我的代码的实际版本有数百个组,我将运行模拟数千次,所以我希望有一种更有效的方法来做到这一点.

I apologize if someone has already asked this question, it is a difficult specific situation to google.如果有人已经问过这个问题,我深表歉意,这是一个很难用谷歌搜索的具体情况。 Thanks!谢谢!

The table would look like this:该表将如下所示: 在此处输入图像描述

For example:例如:

library(tidyverse)
d <- tibble(Group = seq_along(group.dist), n = group.dist)

uncount(d, n, .id = 'Individual')
 # A tibble: 45 × 2 # Groups: Group [10] Group Individual <int> <int> 1 1 1 2 1 2 3 1 3 4 1 4 5 2 1 6 2 2 7 2 3 8 2 4 9 3 1 10 3 2 # … with 35 more rows

Here are two more approaches:这里还有两种方法:

library(data.table)
data.table(Group=1:num.groups)[, .(Individual = seq(1,group.dist[.BY$Group])), by=Group]

OR:或者:

do.call(rbind, lapply(1:num.groups, function(x) data.frame("Group" = x, Individual = 1:group.dist[x])))

Another possible solution, based on dplyr::group_modify :另一种可能的解决方案,基于dplyr::group_modify

library(tidyverse)

num.groups <- 10
mu <- 4
sd <- 1

group.dist <- round(rnorm(num.groups, mean = mu, sd = sd))

data.frame(Group = rep(1:num.groups, group.dist)) %>% 
  group_by(Group) %>% 
  group_modify(~ add_column(.x, Individual = 1:nrow(.x))) %>% 
  ungroup

#> # A tibble: 39 x 2
#>    Group Individual
#>    <int>      <int>
#>  1     1          1
#>  2     1          2
#>  3     1          3
#>  4     1          4
#>  5     2          1
#>  6     2          2
#>  7     2          3
#>  8     2          4
#>  9     3          1
#> 10     3          2
#> # ... with 29 more rows

Or, even better, following @Axeman's suggestion:或者,更好的是,按照@Axeman 的建议:

data.frame(Group = rep(1:num.groups, group.dist)) %>% 
  group_by(Group) %>% 
  mutate(Individual = row_number())
  ungroup

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM