按条件将向量或 data.frame 拆分为间隔并打印间隔的第一个和最后一个值

split vector or data.frame into intervals by condition and print interval's first and last value

我有 data.frame 看起来像这样:

v1 <- c(1:10)
v2 <- c(FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE)
dfb <- data.frame(v1, v2)

> dfb
   v1    v2
1   1 FALSE
2   2 FALSE
3   3  TRUE
4   4 FALSE
5   5 FALSE
6   6 FALSE
7   7  TRUE
8   8 FALSE
9   9 FALSE
10 10 FALSE

我需要那些操作:

  1. 根据V2把data.frame分成区间如果是TRUE
  2. V2TRUE 的行将是最后一个区间元素
  3. 如果最后一个元素不是 TRUE,它将被视为是(这可以通过将 TRUE 添加到最后一个向量位置来轻松实现)
  4. 打印V1作为创建间隔的第一个和最后一个元素

在这个操作之后我的结果应该是这样的:

  > df_final
   Vx Vy
    1 3
    4 7
    8 10

我已经在 v2 向量上尝试了 cumsum,但是 TRUE 值被视为第一个间隔元素而不是最后一个

> split(v2, cumsum(v2==TRUE))
$`0`
[1] FALSE FALSE

$`1`
[1]  TRUE FALSE FALSE FALSE

$`2`
[1]  TRUE FALSE FALSE FALSE

得到df_final

Vy <- c(which(dfb$v2 %in% T),nrow(dfb))
Vx <- c(1,Vy[-length(Vy)]+1)

df_final <- data.frame(Vx,Vy)

拆分 Df

library(data.table)

split_ind <- rleid(dfb$v2)-!(rleid(dfb$v2) %% 2)

split(dfb,split_ind)

你仍然可以使用cumsum,只是稍微调整一下v2:

v3 <- c(TRUE,v2[-length(v2)])
v3
 [1]  TRUE FALSE FALSE  TRUE FALSE FALSE FALSE  TRUE FALSE FALSE

res <- split(v2,cumsum(v3))
res[[length(res)]][length(last(res))] <- T
res
$`1`
[1] FALSE FALSE  TRUE

$`2`
[1] FALSE FALSE FALSE  TRUE

$`3`
[1] FALSE FALSE  TRUE

df_final <- data.frame(Vx=which(v3),Vy=which(unlist(res,use.names=F)))
df_final
  Vx Vy
1  1  3
2  4  7
3  8 10

我也会 post 我的回答在很大程度上受到 Eldioo 的启发,当 V1 是非数值并且避免使用 splitcumsum 函数时,这个也很有用.

输入:

v1 <- letters[1:10]
v2 <- c(FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE)
dfb <- data.frame(v1, v2)

> dfb
   v1    v2
1   a FALSE
2   b FALSE
3   c  TRUE
4   d FALSE
5   e FALSE
6   f FALSE
7   g  TRUE
8   h FALSE
9   i FALSE
10  j FALSE

解决方案:

# data wrangling
library(data.table)
dfb["v3"] <- c(TRUE,dfb$v2[-length(dfb$v2)])
dfb["v4"] <- dfb$v2
dfb$v4[length(dfb$v4)] <- T
Vx <- which(dfb$v3)
Vy <- which(dfb$v4)
Vx <- dfb[Vx, ]$v1
Vy <- dfb[Vy, ]$v1

# for debugging purposes
dfb
   v1    v2    v3    v4
1   a FALSE  TRUE FALSE
2   b FALSE FALSE FALSE
3   c  TRUE FALSE  TRUE
4   d FALSE  TRUE FALSE
5   e FALSE FALSE FALSE
6   f FALSE FALSE FALSE
7   g  TRUE FALSE  TRUE
8   h FALSE  TRUE FALSE
9   i FALSE FALSE FALSE
10  j FALSE FALSE  TRUE

# final results
data.frame(Vx, Vy)
  Vx Vy
1  a  c
2  d  g
3  h  j