在数据框中连续零后查找第一个数字

Finding the first number after consecutive zeros in data frame

我有以下数据框

data <- tibble(ID=rep(c(1:2), each= 9), time = rep(1:9, 2), event = c(1,1,1,0,0,0,0,1,1,1,1,0,0,0,1,0,1,0))

我想检索每个主题的第一行,在连续零 i.e.row 中的第 8 个 data.frame 中的第一个主题和第一个主题中的行号 15 [=16] =]第二个科目

我们可以使用 rle 到 select 每组中第一个连续零之后的第一行 (ID)。

library(dplyr)

data %>%
 group_by(ID) %>%
 slice(with(rle(event == 0), sum(lengths[1:which.max(values)])) + 1)

#     ID  time event
#  <int> <int> <dbl>
#1     1     8     1
#2     2     6     1

一个简洁的答案,如果我正确理解你的问题:

library(dplyr)
data %>% 
  filter(event==1,lag(event)==0)

我的回答与埃里克的非常相似,但需要 2 个零而不是 1 个。

-- 编辑以将结果限制为仅第一次出现而不是全部出现。

library(dplyr)

data <- tibble(ID=rep(c(1:2), each= 9), time = rep(1:9, 2), event = c(1,1,1,0,0,0,0,1,1,1,1,0,0,0,1,0,1,0))

data %>%
  group_by(ID) %>%
  filter(
    event == 1,
    dplyr::lag(event) == 0,
    dplyr::lag(event, 2) == 0,
    cumsum(event == 1 &          # this limits the results to the first occurrence
        dplyr::lag(event, default = 1) == 0 &
        dplyr::lag(event, default = 1, n = 2) == 0) == 1
  )

1) oneAfter0 获取 0 和 1 的向量并将它们粘贴在一起。然后它使用 regexpr 找到第一次出现的 01 和 returns 一个与输入长度相同的逻辑向量。该结果对于第一个 1 的位置为 TRUE,而在其他位置为 FALSE。

ave 用于将其应用于每个组,subset 用于子集化对应于 TRUE 的行。

没有使用包。

oneAfter0 <- function(x) regexpr("01", paste(x, collapse = "")) + 1 == seq_along(x)
subset(data, ave(event, ID, FUN = oneAfter0) == 1)

2) 这也可以像这样使用 dplyr 编写:

library(dplyr)

data %>%
  group_by(ID) %>%
  filter(regexpr("01", paste(event, collapse = "")) + 1 == 1:n()) %>%
  ungroup

这是 Ronak Shah's1 答案的一个有目的的说教版本,以不优雅但逐步的方式展示如何使用 rle 中的 运行 长度来捕获行索引以用于识别 运行s 个零和后面的非零 events

library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
data <- tibble(ID=rep(c(1:2), each= 9), time = rep(1:9, 2), event = c(1,1,1,0,0,0,0,1,1,1,1,0,0,0,1,0,1,0))
runs <- rle(data$event)
runs <- tibble(runs$lengths, runs$values)
colnames(runs) <- c("lengths", "values")
sequences <- sequences <- tibble(lengths = runs$lengths, values = runs$values) %>% mutate(indices = cumsum(runs$lengths))
post_zero <- sequences %>%  filter(values == 0)
result <- left_join(sequences, post_zero, by = "indices") %>% select(1:3) %>% filter(values.x == 1)
colnames(result) <- c("lengths", "runs", "indices")
data[result$indices,]
#> # A tibble: 4 x 3
#>      ID  time event
#>   <int> <int> <dbl>
#> 1     1     3     1
#> 2     2     2     1
#> 3     2     6     1
#> 4     2     8     1

reprex package (v0.3.0)

于 2019-12-16 创建

这是一个 base R 解决方案 rle():

r <- rle(data$event)
df <- data[cumsum(r$lengths)[r$lengths > 1 & r$values==0]+1,]

这样

> df
   ID time event
8   1    8     1
15  2    6     1