【问题标题】:How do I extract either second occurrence of repeated subject ID or first if not repeated?如何提取第二次出现的重复主题 ID 或第一次出现的重复主题 ID?
【发布时间】:2021-07-23 16:02:03
【问题描述】:

我希望提取第二次出现的主题 ID(他们的整行数据)如果该行不重复,则为第一次。

这些数据来自重复访问,我们只对最近非缺失数据中的受试者感兴趣,这意味着受试者要么有“筛查”信息而没有“注射”,要么两者都有。这就是我们定义“基线”的方式。如果受试者两者都有,我们希望保留注射的数据行(治疗前的最后数据),如果只筛选然后筛选(那是治疗前的最后数据并且将等于基线)。

这是一些数据

df1 <- data.frame(ID = c(1, 2, 2, 3, 3, 4),
                  visit = c('screening', 'screening', 'injection', 'screening', 
'injection', 'screening'),
                  var2 = c(1, 6, 3, 12, 0, 2))

我的尝试:

  • 分离并重新合并包含这些主题的两个限定符的数据帧。但是当我这样做时,这些列会被重复,从而产生一个宽而不是长的数据集(当它们显然通过完全相同的 ID 匹配时)。
  • 在 dplyr 中使用具有多个条件的过滤器,但它只捕获那些进行筛选的条件,因为对于重复的主题,它总是首先出现。

建议?

【问题讨论】:

    标签: r


    【解决方案1】:

    使用slice_tail()

    library(dplyr, warn.conflicts = F)
    df1 %>%
      group_by(ID) %>%
      slice_tail()
    
    #> # A tibble: 4 x 3
    #> # Groups:   ID [4]
    #>      ID visit      var2
    #>   <dbl> <chr>     <dbl>
    #> 1     1 screening     1
    #> 2     2 injection     3
    #> 3     3 injection     0
    #> 4     4 screening     2
    

    reprex package (v2.0.0) 于 2021-07-23 创建

    【讨论】:

    • 简洁的答案!太好了!
    【解决方案2】:

    带有subset + ave + match 的基本 R 选项

    subset(
        df1,
        !!ave(match(visit, c("screening", "injection")), ID, FUN = function(x) x == length(x))
    )
    

    给予

      ID     visit var2
    1  1 screening    1
    3  2 injection    3
    5  3 injection    0
    6  4 screening    2
    

    【讨论】:

      【解决方案3】:

      可以使用 dplyr 轻松编码分组条件。这将始终提取每个 ID 的最后一行。

      library(dplyr)
      
      df1 %>% 
        group_by(ID) %>% 
        filter(row_number() == n())
      

      如果您想始终提取第一行或第二行,请在上面的代码顶部使用min()

      df1 %>% 
        group_by(ID) %>% 
        filter(row_number() == min(n(), 2))
      

      在这两种情况下,结果都是格式化为小标题的过滤数据

      # A tibble: 4 x 3
      # Groups:   ID [4]
           ID visit      var2
        <dbl> <fct>     <dbl>
      1     1 screening     1
      2     2 injection     3
      3     3 injection     0
      4     4 screening     2
      

      【讨论】:

      • 如果主题重复超过 2 行将不起作用。 OP 特别需要第二个而不是最新的。
      【解决方案4】:

      使用来自base Rduplicated

      subset(df1, !duplicated(ID, fromLast = TRUE))
        ID     visit var2
      1  1 screening    1
      3  2 injection    3
      5  3 injection    0
      6  4 screening    2
      

      【讨论】:

        【解决方案5】:

        我使用了下面的新管道,因此如果您喜欢或只能使用旧管道(来自 magrittr 而不是 base),请将 |&gt; 替换为 %&gt;%。但基本上我已经分别处理了这些条件。首先我使用unique() 删除重复的行。然后我创建了额外的指标来选择存在相同 ID 的第二行(现在没有重复的行)。

        library(tidyverse)
        
        df1 <- data.frame(ID = c(1, 2, 2, 3, 3, 4),
                          visit = c('screening', 'screening', 'injection', 'screening', 
                                    'injection', 'screening'),
                          var2 = c(1, 6, 3, 12, 0, 2))
        
        df1 |> 
        # Remove exact duplicate rows
          unique() |> 
          group_by(ID) |> 
          # Create two new indicators, one which shows the row number for the group (i.e first, second, ...)
          # The second indicator shows the total number of duplicate entries for the ID
          mutate(row_number_by_id = row_number(), count = n()) |> 
          # Select only the rows that appear second or that only have one entry for the ID
          filter(count == 1 | row_number_by_id == 2)
        #> # A tibble: 4 x 5
        #> # Groups:   ID [4]
        #>      ID visit      var2 row_number_by_id count
        #>   <dbl> <chr>     <dbl>            <int> <int>
        #> 1     1 screening     1                1     1
        #> 2     2 injection     3                2     2
        #> 3     3 injection     0                2     2
        #> 4     4 screening     2                1     1
        

        reprex package (v2.0.0) 于 2021-07-23 创建

        【讨论】:

          【解决方案6】:

          您可以使用min()函数来引用访问字符串的字母顺序。

          > df1 %>% filter(visit == "screening" || visit == "injection") %>%
          group_by(ID) %>% summarise(min(visit))
          # A tibble: 4 x 2
               ID `min(visit)`
            <dbl> <chr>       
          1     1 screening   
          2     2 injection   
          3     3 injection   
          4     4 screening   
          

          查看其他汇总函数here

          或者使用row_number()

          df1 %>% filter(visit == "screening" || visit == "injection") %>%
          group_by(ID) %>% filter(row_number() == max(row_number()))
          

          如果您有另一列可以识别这些行的顺序,我建议您使用该列。

          【讨论】:

            猜你喜欢
            • 2016-09-10
            • 2019-09-20
            • 1970-01-01
            • 1970-01-01
            • 2014-02-08
            • 2014-12-14
            • 2022-11-22
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多