【问题标题】:Create new count variable conditional on previous values within group根据组内先前的值创建新的计数变量
【发布时间】:2020-07-22 07:34:50
【问题描述】:

我有一个包含组和时间 ID 的数据框。现在我想创建一个新的计数变量,称为 X2,以每个组中以前的 X1 值为条件。

假设我有以下数据框,变量grouptimeX1,并想创建X2X2 的值应该是一个计数变量,指示自给定组中 X1 上次等于 1 以来的句点数(即行数)。如果X1 之前的所有值都是0,则X2 应该是缺失的。

          group     time       X1        X2 
1          1         1         0         NA  
2          1         2         0         NA  
3          1         3         1         NA  
4          1         4         0         0  
5          1         5         1         1
6          2         1         0         NA  
7          2         2         1         NA  
8          2         3         1         0  
9          2         4         1         0  
10         2         5         0         0  
11         3         1         0         NA  
12         3         2         0         NA  
13         3         3         0         NA  
14         3         4         1         NA  
15         3         5         0         0  
16         4         1         1         NA  
17         4         2         0         0  
18         4         3         0         1  
19         4         4         0         2  
20         4         5         1         3    
data_test <- data.frame(
   group = rep(1:4, each = 5), 
   time = rep(1:5, n = 4), 
   X1 = c(0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1), 
   X2 = c(NA, NA, NA, 0, 1, NA, NA, 0, 0, 0, NA, NA, NA, NA, 0, NA, 0, 1, 2, 3))

我可以使用带有cumsum()==0 的if 命令轻松创建NA。但是,我不知道如何处理另一部分,即创建计数。

任何帮助将不胜感激 - 如果可能的话,请使用 dplyr

非常感谢。

【问题讨论】:

    标签: r dplyr count conditional-statements lag


    【解决方案1】:

    这不是很优雅,但它包含了我认为提供的规则。

    X1 为 1 并使用 fill 的行号添加一列,以便您可以使用适用于该条件的最新行号。

    要计算X2_new,如果X1 为0,则为组内的当前行号减去X1 为1 的最后一个行号之间的差。如果X1 为1(而不是第一个 X1 组中的 1 个),然后进行类似的计算,但在前面的 rn 参考上。

    library(tidyverse)
    
    data_test %>%
      group_by(group) %>%
      mutate(rn = ifelse(X1 == 1, row_number(), NA)) %>%
      fill(rn) %>%
      mutate(X2_new = ifelse(X1 == 0 & row_number() > rn, row_number() - rn - 1, NA),
             X2_new = ifelse(X1 == 1 & !is.na(lag(rn)), row_number() - lag(rn) - 1, X2_new)) %>%
      select(-rn)
    

    输出

    # A tibble: 20 x 5
    # Groups:   group [4]
       group  time    X1    X2 X2_new
       <int> <int> <dbl> <dbl>  <dbl>
     1     1     1     0    NA     NA
     2     1     2     0    NA     NA
     3     1     3     1    NA     NA
     4     1     4     0     0      0
     5     1     5     1     1      1
     6     2     1     0    NA     NA
     7     2     2     1    NA     NA
     8     2     3     1     0      0
     9     2     4     1     0      0
    10     2     5     0     0      0
    11     3     1     0    NA     NA
    12     3     2     0    NA     NA
    13     3     3     0    NA     NA
    14     3     4     1    NA     NA
    15     3     5     0     0      0
    16     4     1     1    NA     NA
    17     4     2     0     0      0
    18     4     3     0     1      1
    19     4     4     0     2      2
    20     4     5     1     3      3
    

    【讨论】:

      【解决方案2】:

      使用 dplyr 包中的管道 (%&gt;%)、mutategroup_bylag 函数

      library(dplyr)
      data_test %>%
        group_by(group) %>%
        mutate(X2 = ifelse(lag(X1) == 1, 0, lag(X2) + 1))
      

      这确实假设time 的差异始终为 1,如您的示例数据所示。如果time 在您的数据中发生变化,并且X2 应该反映time 中的差异:

      data_test %>%
        group_by(group) %>%
        mutate(X2 = ifelse(lag(X1) == 1, 0, lag(X2) + (time - lag(time))))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-03-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多