【问题标题】:Subset data based on conditional statement基于条件语句的子集数据
【发布时间】:2020-10-23 18:12:18
【问题描述】:

我想知道是否有一种方法可以将 ifelse 语句和过滤器函数(在 dplyr 包中)组合成一个数据帧的子集。考虑数据

df<-data.frame(id=c(1,1,1,2,2,2,2,3,3),
            A=c(3,6,2,5,4,3,8,9,8),
           D1=c(0,0,0,1,1,0,0,0,0),
           D2=c(1,0,0,0,0,1,1,0,1))

我想为每个 id 删除 D2=1 或 D1=D2=0 之后的行。预期的输出看起来像

df<-data.frame(id=c(1,2,2,2,3),
            A=c(3,5,4,3,9),
           D1=c(0,1,1,0,0),
           D2=c(1,0,0,1,0))

我已经多次尝试使用 group_by 和 filter 函数来解决这个问题,但似乎需要条件语句,但我发现很难将这些与 filter 函数结合起来。我遇到了几个关于子集数据的问答(例如How to subset data by filtering and grouping efficiently in R),但这些都没有回答我的问题。我非常感谢您对此提供的任何帮助。

【问题讨论】:

  • 其中一个答案是否解决了您的问题,TRichard?如果有,请采纳。谢谢!

标签: r dataframe filter dplyr subset


【解决方案1】:

dplyr:

df %>%
  group_by(id) %>%
  filter(row_number() == n() | rev(cumany(rev(!(D2 == 1 | (D1 == D2 & D2 == 0))))))
# # A tibble: 5 x 4
# # Groups:   id [3]
#      id     A    D1    D2
#   <dbl> <dbl> <dbl> <dbl>
# 1     1     2     0     0
# 2     2     5     1     0
# 3     2     4     1     0
# 4     2     8     0     1
# 5     3     8     0     1

【讨论】:

    【解决方案2】:

    您似乎不需要在这里使用dplyr(除非我遗漏了什么)。试试这个:

    df<-data.frame(id=c(1,1,1,2,2,2,2,3,3),
                   A=c(3,6,2,5,4,3,8,9,8),
                   D1=c(0,0,0,1,1,0,0,0,0),
                   D2=c(1,0,0,0,0,1,1,0,1))
    
    del = c()
    
    for (i in 1:nrow(df)){
      if (df$D2[i] == 1 | (df$D1[i] ==0 & df$D2[i] == 0)){
        del = c(del, i)
      }
    }
    
    df = df[del,]
    

    【讨论】:

      【解决方案3】:

      dplyr 中,您可以找出满足条件的第一个索引,并为每个组选择满足条件之前出现的行。

      library(dplyr)
      df %>%
        group_by(id) %>%
        filter(row_number() <= which(D1 == 0 & D2 == 0 | D2 == 1)[1])
      
      
      #     id     A    D1    D2
      #  <dbl> <dbl> <dbl> <dbl>
      #1     1     3     0     1
      #2     2     5     1     0
      #3     2     4     1     0
      #4     2     3     0     1
      #5     3     9     0     0
      

      上述工作假设每组中至少有一行满足条件。一般情况下,可能存在没有任何行满足条件的情况,我们希望选择组中可以使用的所有行:

      df %>%
        group_by(id) %>%
        slice({
           inds <- which(D1 == 0 & D2 == 0 | D2 == 1)[1]
           if(!is.na(inds)) -((inds + 1):n()) else seq_len(n())})
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-12-06
        • 2016-03-19
        • 1970-01-01
        • 2020-01-22
        • 1970-01-01
        • 2014-09-13
        • 1970-01-01
        相关资源
        最近更新 更多