在数据框中连续零后查找第一个数字
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 个零和后面的非零 event
s
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
我有以下数据框
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 个零和后面的非零 event
s
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