【问题标题】:How to select rows with certain values on a combination of two variables within a group in R如何在R中的一个组中的两个变量的组合上选择具有某些值的行
【发布时间】:2019-09-22 01:15:47
【问题描述】:

这是我之前提出的 R 问题的扩展:How to select rows with certain values within a group in R

我在这个问题上得到了很大的帮助,但现在变得有点复杂了,我希望得到如何处理这个问题的建议。

我的数据如下所示:

dd <- read.table(text="
    event.timeline.ys     ID     year    group  outcome
                 1                   2     800033 2008    A  3
                 2                   1     800033 2009    A  3
                 3                   0     800033 2010    A  NA   
                 4                  -1     800033 2011    A  2  
                 5                  -2     800033 2012    A  1  
                 15                  0     800076 2008    B  2
                 16                 -1     800076 2009    B  NA
                 17                  5     800100 2014    C  4     
                 18                  4     800100 2015    C  4  
                 19                  2     800100 2017    C  4  
                 20                  1     800100 2018    C  3   
                 30                  0     800125 2008    A  2   
                 31                 -1     800125 2009    A  1   
                 32                 -2     800125 2010    A  NA
                 33                  2     800031 2008    A  3
                 34                  1     800031 2009    A  3
                 35                  0     800031 2010    A  NA   
                 36                 -1     800031 2011    A  NA  
                 37                 -2     800031 2012    A  1", header=TRUE)

我只想选择组 (ID) 中的特殊行。应根据以下过程选择这些行:

如果可能,我希望在 event.timeline.ys 上为每个参与者保留最后一行的正值(即,ID 组中 event.timeline.ys >= 0 的最后一行),其中结果变量不是 NA 但具有有效值(例如,对于 ID == 800033,这将是第 2 行)。

此外,我想在 event.timeline.ys 上为每个参与者保留第一行的负值(即,ID 组中 event.timeline.ys

在 ID == 800076 的特殊情况下,当 event.timeline.ys

ID = 800100 的人在 event.timeline.ys 上没有任何负值。在这种情况下,我只想保留 event.timeline.ys >= 0 的最后一行。

应删除所有其他行。最终的数据框如下所示:

      event.timeline.ys         ID     year    group  outcome
2                     1     800033     2009    A            3
4                    -1     800033     2011    A            2  
15                    0     800076     2008    B            2
16                   -1     800076     2009    B           NA
20                    1     800100     2018    C            3   
30                    0     800125     2008    A            2   
31                   -1     800125     2009    A            1
34                    1     800031     2009    A            3
37                   -2     800031     2012    A            1

我非常感谢有关如何解决此问题的建议。我已经试过了:

dd %>% 
  group_by(ID) %>% 
  filter(row_number() == last(which(event.timeline.ys >= 0 & outcome >= 0)) | 
           row_number() == first(which(event.timeline.ys < 0 & outcome >= 0)))

但是,不幸的是,我丢失了第 16 行(对于 ID == 800076)。

非常感谢!

【问题讨论】:

    标签: r function dplyr


    【解决方案1】:

    使用dplyr:

    dd %>%
    group_by(ID, event.timeline.ys>=0) %>%
    arrange(ID, event.timeline.ys>=0, abs(event.timeline.ys)) %>%
    filter(!is.na(outcome) | n()==1) %>%
    filter(row_number()==1) %>%
    ungroup() %>%
    select(-one_of('event.timeline.ys >= 0'))
    

    输出:

      event.timeline.ys     ID  year group outcome
                  <int>  <int> <int> <fct>   <int>
    1                -1 800033  2011 A           2
    2                 1 800033  2009 A           3
    3                -1 800076  2009 B          NA
    4                 0 800076  2008 B           2
    5                 1 800100  2018 C           3
    6                -1 800125  2009 A           1
    7                 0 800125  2008 A           2
    

    【讨论】:

    • 非常感谢!我真的很感谢你的帮助。我喜欢看到有不同的方法可以达到相同的结果。对于不太熟悉管道、函数和循环的人(像我一样,我刚刚开始在 R 中训练自己),这看起来也是一个清晰明了的解决方案!
    【解决方案2】:

    这是使用dplyrwrapr 的管道%.&gt;% 的解决方案。 我正在添加 outcome_na 并通过它进行安排以满足“没有任何非 NA 值”的条件。

    library(dplyr)
    library(wrapr)
    
    dd %>%
      group_by(ID) %>%
      mutate(outcome_na = !is.na(outcome)) %.>%
      bind_rows(
        filter(., event.timeline.ys >= 0) %>% arrange(outcome_na, year) %>% slice(n()),
        filter(., event.timeline.ys < 0) %>% arrange(desc(outcome_na), year) %>% slice(1)
      ) %>%
      arrange(ID) %>%
      select(-outcome_na)
    

    【讨论】:

    • 嘿,我在上面的数据示例中添加了另一个人(ID == 800031)。使用你的代码,我会得到第 34 行(这是正确的)和第 36 行。但是,在第 36 行,这个人在结果变量上有 NA。我想获得第 37 行(在 event.timeline.ys 上具有负值的第一行,在结果变量上也有一个有效值。我如何调整您的代码才能得到这个?
    • @MarieB。您还必须按outcome_na 排列event.timeline.ys &lt; 0,但这次按降序排列,因为您想要的不是最后一行而是第一行。
    【解决方案3】:

    为了与我之前使用data.table 的答案保持一致,我们可以使用ifelse 条件来选择行

    library(data.table)
    setDT(dd)
    dd[, .SD[na.omit(c(ifelse(any(event.timeline.ys >= 0 & !is.na(outcome)),
                              last(which(event.timeline.ys >= 0 & !is.na(outcome))), 
                              last(which(event.timeline.ys >= 0))),
                       ifelse(any(event.timeline.ys < 0 & !is.na(outcome)),
                              first(which(event.timeline.ys < 0 & !is.na(outcome))), 
                              first(which(event.timeline.ys < 0)))))],
       by=ID]
    
    
           ID event.timeline.ys year group outcome
    1: 800033                 1 2009     A       3
    2: 800033                -1 2011     A       2
    3: 800076                 0 2008     B       2
    4: 800076                -1 2009     B      NA
    5: 800100                 1 2018     C       3
    6: 800125                 0 2008     A       2
    7: 800125                -1 2009     A       1
    8: 800031                 1 2009     A       3
    9: 800031                -2 2012     A       1
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-02-18
      • 1970-01-01
      • 1970-01-01
      • 2019-04-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多