首页 文章

R&dplyr:为选定的组成员分配组级特征

提问于
浏览
-1

我有一个大型数据集,通过分组变量= grp 分成许多小组;组中的所有成员按较大数据集的顺序连续 . 每个组的成员都有一个id代码(= id ),并从1开始按顺序编号 . 在一个组中,某些成员符合逻辑标准= is_child . 每个成员都有一个变量( momloc ),其中包含零或另一个组成员(母亲,如果存在)的ID号 .

我希望为数据集中的每个人分配momloc等于其ID的组成员数,如果没有则为零 . 我试图在dplyr中执行此操作,因为我已经在那里设置了组,并且我的代码有效,但它是Rube Goldberg的嵌套ifelse函数的装置,它为中间值添加了两个额外的列,其中一个包含一个向量,经历三次数据集,并且非常慢 . 必须有一个比这更好的方法 . 我正在纠缠于mutate的不同语法,处理行和汇总,处理组 .

以下是简化的数据集和期望的结果

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)

3 回答

  • 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) 将数据帧拆分为多个数据帧,每个数据帧一个 .

    然后,我们使用 lapply() 将操作应用于列表中的每个data.frame . 对于每个这些数据帧,我们按 idgrp 进行分组 - 即使这意味着唯一的'groups' . 我们也可以只对 id 进行分组,但是对两者进行分组意味着我们可以保留两列 .

    现在,列表中的每个data.frame都包含3列

    • id

    • grp

    • NumChildren

    现在,我们可以使用 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
    
  • 1

    我很容易误解你的问题 . 但我认为 momlocgrp 是您正在寻找的:

    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
    

    请注意,我将 grpid 更改为第2行和第3行的因子 .

  • 0

    我建议只使用 dplyr 解决方案 .

    首先,我只保留孩子(假设您只想将它们计为 out[6] = 2 而不是3) . 然后,我使用 count() 创建 momloc 的频率表,并将其合并到原始数据 .

    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
    

相关问题