【问题标题】:Removing a group with conditional statement in r在r中删除带有条件语句的组
【发布时间】:2020-08-08 16:52:36
【问题描述】:

条件语句是,在任何情况下,如果有两个或多个连续行的值大于1,则应该删除该组。

例如:

Event<- c(1,1,1,1,2,2,2,2,2,2,3,3,3,3,3)
Value<- c(1,0,0,0,8,7,1,0,0,0,8,0,0,0,0)
A<- data.frame(Event, Value)

Event   Value
  1       1
  1       0
  1       0
  1       0
  2       8
  2       7
  2       1
  2       0
  2       0
  2       0
  3       8
  3       0
  3       0
  3       0
  3       0

在这个例子中,事件 2 的组应该被删除,因为它有两个连续的行的值大于 1。所以它应该看起来像:

Event   Value
  1       1
  1       0
  1       0
  1       0
  3       8
  3       0
  3       0
  3       0
  3       0

有什么建议吗?

【问题讨论】:

  • 是的,超过 1。
  • 如果一个组的连续行超过 1 行,并且值 >1,那么我想删除该组
  • 对不起,一个组连续超过 1 行。如示例所示
  • 在一个组中,是否总是像本例中那样,值是递减的?或者我们是否可以在同一个组中:3、0、1、5 的顺序(这意味着不应删除该组,因为大于 1 的数字不连续)?
  • 没有必要。在您的示例 (3,0,1,5) 中,您是对的,它不应该被删除。

标签: r for-loop if-statement dplyr conditional-statements


【解决方案1】:

使用dplyr

A %>%
  group_by(Event) %>%
  mutate(consec = if_else(Value > 1, row_number(), 0L),
         remove = if_else(consec > 1,"Y","N")) %>%
  filter(!any(remove == "Y")) %>%
  select(-c("consec","remove"))

【讨论】:

    【解决方案2】:

    baseR 方法:

    # split the dataframe by event into separate lists, record whether values are > 1 (T/F)
    A_split <- split(A$Value > 1, Event)
    
    # for each item in the list, record the number of consecutive T values;
    # make T/F vector "keep" with row names corresponding to A$Event
    keep <- sapply(A_split, function(x) sum(x[1:length(x) - 1] * x[2:length(x)])) == 0 
    
    # convert keep to numeric vector of A$Event values
    keep <- as.numeric(names(keep == T))
    
    # subset A based on keep vector
    A[A$Event %in% keep, ]
    
    

    【讨论】:

      【解决方案3】:

      我们可以按组使用rle

      library(dplyr)
      A %>%
       group_by(Event) %>%
       filter(!any(with(rle(Value > 1), lengths[values] > 1)))
       #Opposite way using all
       #filter(all(with(rle(Value > 1), lengths[values] < 2)))
      
      #  Event Value
      #  <dbl> <dbl>
      #1     1     1
      #2     1     0
      #3     1     0
      #4     1     0
      #5     3     8
      #6     3     0
      #7     3     0
      #8     3     0
      #9     3     0
      

      同样的逻辑也可以用在base R中:

      subset(A, !ave(Value > 1, Event, FUN = function(x) 
                     any(with(rle(x), lengths[values] > 1))))
      

      还有data.table

      library(data.table)
      setDT(A)[, .SD[!any(with(rle(Value > 1), lengths[values] > 1))], Event]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-05-05
        • 1970-01-01
        • 1970-01-01
        • 2016-08-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多