我有一个大型数据集,通过分组变量= grp
划分为许多小组;组中的所有成员按较大数据集的顺序连续。每个组的成员都有一个id代码(= id
),并从1开始按顺序编号。在一个组中,某些成员符合逻辑标准= is_child
。每个成员都有一个变量(momloc
),其中包含另一个组成员(母亲,如果有的话)的零或ID号。
我希望为数据集中的每个人分配momloc等于其ID的组成员数,如果没有,则为零。我试图在dplyr中执行此操作,因为我已经在那里设置了组,并且我有可用的代码,但它是嵌套ifelse函数的Rube Goldberg装置,为中间值添加了两个附加列,其中一个包含向量,经历了三次数据集,并且非常慢。必须有一个比这更好的方法。我在变异,处理行和汇总,处理组的不同语法中纠缠不清。
以下是简化的数据集和期望的结果
grp <- c(1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2)
id <- c(1, 2, 3, 4, 1, 2, 3, 4, 5, 6, 7)
is_child <- c(0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0)
momloc <- c(0, 0, 2, 2, 0, 0, 0, 3, 2, 2, 2)
data <- tibble(grp, id, is_child, momloc)
期望的输出:
out = c(0, 2, 0, 0, 0, 2, 1, 0, 0, 0, 0)
答案 0 :(得分:1)
我很容易误解你的问题。但我认为table()
momloc
和grp
正是您所寻找的:
library(tidyverse)
grp <- c(1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2) %>% factor
id <- c(1, 2, 3, 4, 1, 2, 3, 4, 5, 6, 7) %>% factor
is_child <- c(0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0)
momloc <- c(0, 0, 2, 2, 0, 0, 0, 3, 2, 2, 2)
data <- tibble(grp, id, is_child, momloc)
out = c(0, 2, 0, 0, 0, 2, 1, 0, 0, 0, 0)
data2 <- filter(data, is_child == 1)
data3 <- table(id = factor(data2$momloc, levels = levels(id)), grp = data2$grp) %>%
as.data.frame(responseName = "out")
left_join(data, data3, by = c("grp", "id"))
#> # A tibble: 11 x 5
#> grp id is_child momloc out
#> <fct> <fct> <dbl> <dbl> <int>
#> 1 1 1 0. 0. 0
#> 2 1 2 0. 0. 2
#> 3 1 3 1. 2. 0
#> 4 1 4 1. 2. 0
#> 5 2 1 0. 0. 0
#> 6 2 2 0. 0. 2
#> 7 2 3 0. 0. 1
#> 8 2 4 1. 3. 0
#> 9 2 5 1. 2. 0
#> 10 2 6 1. 2. 0
#> 11 2 7 0. 2. 0
all(cbind(data, out) == left_join(data, data3, by = c("grp", "id")))
#> [1] TRUE
请注意,我更改了grp
和id
以考虑第2行和第3行。
答案 1 :(得分:1)
以下是使用dplyr
的解决方案。
data.moms <- data %>%
split(grp) %>%
lapply(., function(data.grp) {
data.grp %>% group_by(id, grp) %>% summarise(NumChildren = sum(.$momloc == id))
}) %>% do.call(rbind, .)
我们首先使用split(grp)
将数据框拆分为多个数据框,每个数据框一个。{/ p>
然后,我们使用lapply()
将操作应用于列表中的每个data.frame。
对于每个数据框架,我们按id
和grp
分组 - 即使这意味着唯一的“群组”。我们也可以仅在id
上进行分组,但在两者上进行分组意味着我们可以保留两列。
现在,列表中的每个data.frame都包含3列
现在,我们可以使用do.call(rbind, .)
重新组合汇总的数据框。
> data.moms
# A tibble: 11 x 3
# Groups: id [7]
id grp NumChildren
<dbl> <dbl> <int>
1 1.00 1.00 0
2 2.00 1.00 2
3 3.00 1.00 0
4 4.00 1.00 0
5 1.00 2.00 0
6 2.00 2.00 3
7 3.00 2.00 1
8 4.00 2.00 0
9 5.00 2.00 0
10 6.00 2.00 0
11 7.00 2.00 0
答案 2 :(得分:0)
我仅使用dplyr
提出解决方案。
首先,我只保留孩子(假设您只想将它们计为out[6] = 2
而不是3)。然后,我使用momloc
创建count()
的频率表,并将其合并到原始数据中。
data %>%
filter(is_child == 1) %>% # only count for children
group_by(grp) %>%
count(momloc) %>%
right_join(data, by = c("grp" = "grp", "momloc" = "id")) %>%
rename(
id = momloc,
momloc = momloc.y,
out = n
) %>%
mutate(out = ifelse(is.na(out), 0, out))
#> # A tibble: 11 x 5
#> # Groups: grp [2]
#> grp id out is_child momloc
#> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 1 1 0 0 0
#> 2 1 2 2 0 0
#> 3 1 3 0 1 2
#> 4 1 4 0 1 2
#> 5 2 1 0 0 0
#> 6 2 2 2 0 0
#> 7 2 3 1 0 0
#> 8 2 4 0 1 3
#> 9 2 5 0 1 2
#> 10 2 6 0 1 2
#> 11 2 7 0 0 2