【问题标题】:Detect sequences rowwise逐行检测序列
【发布时间】:2021-11-09 12:05:39
【问题描述】:

请查看玩具数据以创建“检查”列(解决方案)。如果序列中有 3 个值(从 2018 年到 2021 年,按行排列)>=20,则该值应为 TRUE,否则为 FALSE。

首选 dplyr 解决方案。原始数据集有数百列和数千行。 NA 可以在任何地方。

test<-data.frame(country=c("US","UK","RU","GR","BE"),
             "y_2018"=c(NA,30,20,40,10),
             "y_2019"=c(10,10,20,20,20),
             "y_2020"=c(20,NA,30,20,20),
             "y_2021"=c(NA,70,10,10,NA),
             check=c(F,F,T,T,F))

【问题讨论】:

  • 对于序列30, 10, 20, 40会有什么结果?
  • 好问题。 30,10,20,40 -> 错误。但是一个序列中超过3个也应该是TRUE(即:20,20,20,20->TRUE)

标签: r dplyr seq rowwise


【解决方案1】:

使用来自collapsedapply

library(collapse)
library(data.table)
test$check <- dapply(get_vars(test, is.numeric), MARGIN = 1,
       FUN = function(x) any(table(NA^(x < 20)*rleid(x >= 20))>=3))
test$check
[1] FALSE FALSE  TRUE  TRUE FALSE

【讨论】:

    【解决方案2】:

    另一种不使用 dplyr 的方法(我更改了测试数据以包含 30, 10, 20, 40) 案例):

    test<-data.frame(country=c("US","UK","RU","GR","BE"),
                     "y_2018"=c(NA,30,20,30,10),
                     "y_2019"=c(10,10,20,10,20),
                     "y_2020"=c(20,NA,30,20,20),
                     "y_2021"=c(NA,70,10,40,NA),
                     check=c(F,F,T,T,F))
    
    rownames(test) <- seq(1:nrow(test))
    
    
    # Choose only rows whose number of columns with x >=20 is greater than 2
    cond1  <- apply(test[2:5], 2, function(x) x >= 20)
    
    cond2  <- apply(cond1, 1, function(x) length(which(x==TRUE)) > 2)
    
    data1 <- data.frame(cond1[cond2,])
    
    
    # Check if the condition of x>=20 is sequential across columns
    aa <- ifelse(data1$y_2018 == data1$y_2019 & data1$y_2019 == data1$y_2020, TRUE, FALSE)
    
    bb <- ifelse(data1$y_2019 == data1$y_2020 & data1$y_2020 == data1$y_2021, TRUE, FALSE)
    
    cc <- data.frame(aa, bb)
    
    cc$final <- ifelse(cc$aa==TRUE | cc$bb==TRUE, TRUE, FALSE)
    
    
    # Select the appropriate rows
    data2 <- data.frame(data1[cc$final,])
    
    test2 <- test[rownames(data2),]
    
    

    【讨论】:

      【解决方案3】:

      这是一种使用rle的方法-

      library(dplyr)
      
      test %>%
        rowwise() %>%
        mutate(check = {
          tmp <- rle(c_across(starts_with('y')) >= 20)
          any(tmp$lengths[tmp$values] >= 3, na.rm = TRUE)
        }) %>%
        ungroup
      
      # country y_2018 y_2019 y_2020 y_2021 check
      #  <chr>    <dbl>  <dbl>  <dbl>  <dbl> <lgl>
      #1 US          NA     10     20     NA FALSE
      #2 UK          30     10     NA     70 FALSE
      #3 RU          20     20     30     10 TRUE 
      #4 GR          40     20     20     10 TRUE 
      #5 BE          10     20     20     NA FALSE
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-05-28
        • 2015-02-03
        • 2011-07-20
        • 2018-03-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多