按条件将向量或 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
我需要那些操作:
- 根据
V2
把data.frame分成区间如果是TRUE
V2
为 TRUE
的行将是最后一个区间元素
- 如果最后一个元素不是
TRUE
,它将被视为是(这可以通过将 TRUE
添加到最后一个向量位置来轻松实现)
- 打印
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
是非数值并且避免使用 split
和 cumsum
函数时,这个也很有用.
输入:
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
我有 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
我需要那些操作:
- 根据
V2
把data.frame分成区间如果是TRUE
V2
为TRUE
的行将是最后一个区间元素- 如果最后一个元素不是
TRUE
,它将被视为是(这可以通过将TRUE
添加到最后一个向量位置来轻松实现) - 打印
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
是非数值并且避免使用 split
和 cumsum
函数时,这个也很有用.
输入:
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