首页 > 解决方案 > 在一行中搜索 r 中的一系列值

问题描述

解释这是一项复杂的任务,但我试图逐行查看几列,以搜索 3 次或更多连续出现的模式FALSE,但前提是这之前至少有一个TRUE.

在找到这种模式的地方,我想添加一个新列date_lost,显示发生这种情况的日期(日期取自列标题 - 我知道这不是命名列的最佳方式,但这就是数据框的方式被建立)

一个简单的数据框可能如下所示:

library(tidyverse)

df <- 
  tribble(
    ~id, ~`01/01/18`, ~`02/01/18`, ~`03/01/18`, ~`04/01/18`, ~`05/01/18`,
    1,        NA,        NA,      TRUE,      TRUE,     FALSE,
    2,      TRUE,      TRUE,     FALSE,     FALSE,     FALSE,
    3,      TRUE,     FALSE,     FALSE,     FALSE,      TRUE,
    4,     FALSE,      TRUE,     FALSE,      TRUE,     FALSE,
    5,      TRUE,     FALSE,     FALSE,      TRUE,      TRUE,
    6,     FALSE,     FALSE,     FALSE,      TRUE,     FALSE,
    7, NA, NA, NA, NA, NA
  )

> df
# A tibble: 7 x 6
     id `01/01/18` `02/01/18` `03/01/18` `04/01/18` `05/01/18`
  <dbl> <lgl>      <lgl>      <lgl>      <lgl>      <lgl>     
1     1 NA         NA         TRUE       TRUE       FALSE     
2     2 TRUE       TRUE       FALSE      FALSE      FALSE     
3     3 TRUE       FALSE      FALSE      FALSE      TRUE      
4     4 FALSE      TRUE       FALSE      TRUE       FALSE     
5     5 TRUE       FALSE      FALSE      TRUE       TRUE      
6     6 FALSE      FALSE      FALSE      TRUE       FALSE     
7     7 NA         NA         NA         NA         NA     

该函数将识别在第 2 行和第 3 行中找到此模式,并在新列date_lost中添加日期(05/01/18第 204/01/18行和第 3 行)。NA如果未找到此模式,则其他行可能有,如下所示:

# A tibble: 7 x 7
     id `01/01/18` `02/01/18` `03/01/18` `04/01/18` `05/01/18` date_lost
  <dbl> <lgl>      <lgl>      <lgl>      <lgl>      <lgl>      <chr>    
1     1 NA         NA         TRUE       TRUE       FALSE      NA       
2     2 TRUE       TRUE       FALSE      FALSE      FALSE      05/01/18 
3     3 TRUE       FALSE      FALSE      FALSE      TRUE       04/01/18 
4     4 FALSE      TRUE       FALSE      TRUE       FALSE      NA       
5     5 TRUE       FALSE      FALSE      TRUE       TRUE       NA       
6     6 FALSE      FALSE      FALSE      TRUE       FALSE      NA       
7     7 NA         NA         NA         NA         NA         NA    

我确信这可以在 中以一种优雅的方式完成r,但我只是无法找到这样的方式。非常感谢您的帮助

标签: r

解决方案


这是一个解决方案,它使用了一些重塑(使用列而不是行)和一些分组,以便发现(3+)连续的 FALSE 案例,其中(1+) TRUE 在它们之前。

library(tidyverse)
library(data.table)

df <- 
  tribble(
    ~id, ~`01/01/18`, ~`02/01/18`, ~`03/01/18`, ~`04/01/18`, ~`05/01/18`,
    1,        NA,        NA,      TRUE,      TRUE,     FALSE,
    2,      TRUE,      TRUE,     FALSE,     FALSE,     FALSE,
    3,      TRUE,     FALSE,     FALSE,     FALSE,      TRUE,
    4,     FALSE,      TRUE,     FALSE,      TRUE,     FALSE,
    5,      TRUE,     FALSE,     FALSE,      TRUE,      TRUE,
    6,     FALSE,     FALSE,     FALSE,      TRUE,     FALSE,
    7, NA, NA, NA, NA, NA
  )


df %>%
  gather(date, value, -id) %>%                      # reshape data
  arrange(id) %>%                                   # arrange data by id
  group_by(id2 = rleid(id, value)) %>%              # create a new grouping (to spot consequtive FALSE cases)
  mutate(value = ifelse(is.na(as.character(value)), 
                        ".", 
                        as.character(value)),       # update value variable (NAs will break the grouping, so we replace them with ".")
         false_in_row = sum(value == "FALSE")) %>%  # count how many FALSE in a row
  group_by(id) %>%                                  # group by id column
  mutate(flag = cumsum(value == "TRUE")) %>%        # create a flag to spot if you had TRUE before FALSE cases
  filter(flag >= 1 & false_in_row >= 3) %>%         # keep only conditions you specified
  summarise(date_lost = nth(date, 3)) %>%             # get date the matches your conditions
  right_join(df, by="id")                           # join original dataset

# # A tibble: 7 x 7
#      id date_lost `01/01/18` `02/01/18` `03/01/18` `04/01/18` `05/01/18`
#   <dbl> <chr>     <lgl>      <lgl>      <lgl>      <lgl>      <lgl>     
# 1     1 NA        NA         NA         TRUE       TRUE       FALSE     
# 2     2 05/01/18  TRUE       TRUE       FALSE      FALSE      FALSE     
# 3     3 04/01/18  TRUE       FALSE      FALSE      FALSE      TRUE      
# 4     4 NA        FALSE      TRUE       FALSE      TRUE       FALSE     
# 5     5 NA        TRUE       FALSE      FALSE      TRUE       TRUE      
# 6     6 NA        FALSE      FALSE      FALSE      TRUE       FALSE     
# 7     7 NA        NA         NA         NA         NA         NA 

推荐阅读