R 如何提取起始信号和结束信号之间的所有行?
我有以下R 如何提取起始信号和结束信号之间的所有行?,r,dataframe,filtering,R,Dataframe,Filtering,我有以下df,我想根据以下开始和结束信号提取所有行 启动信号:当状态从1变为0时 结束信号:当状态从0变为-1时 df <- data.frame(time = rep(1:14), status = c(0,1,1,0,0,0,-1,0,1,0,0,0,-1,0)) time status 1 1 0 2 2 1 3 3 1 4 4 0 5 5 0 6 6 0 7
df
,我想根据以下开始和结束信号提取所有行
启动信号:当状态从1变为0时
结束信号:当状态从0变为-1时
df <- data.frame(time = rep(1:14), status = c(0,1,1,0,0,0,-1,0,1,0,0,0,-1,0))
time status
1 1 0
2 2 1
3 3 1
4 4 0
5 5 0
6 6 0
7 7 -1
8 8 0
9 9 1
10 10 0
11 11 0
12 12 0
13 13 -1
14 14 0
我们计算开始和结束标记,然后使用这些值和(开始-结束)的累积和来筛选行。
(求和(开始)-求和(结束)>1)
是一个小把戏,以避免开始但未结束的第2行打乱累积计数;否则,第14行将不自觉地被包括在内
require(dplyr)
df %>% mutate(start=(status==1), end=(status==-1)) %>%
filter(!start & !end & (cumsum(start)-cumsum(end)>1) ) %>%
select(-start, -end)
# time status
# 1 4 0
# 2 5 0
# 3 6 0
# 4 10 0
# 5 11 0
# 6 12 0
有点难看,但是您可以始终循环这些值,并保留一个标志来确定是否应该保留元素
keepers <- rep(FALSE, nrow(df))
flag <- FALSE
for(i in 1:(nrow(df)-1)) {
if(df$status[i] == 1 && df$status[i+1] == 0) {
flag <- TRUE
next # keep signal index false
}
if(df$status[i] == -1 && df$status[i+1] == 0) {
flag <- FALSE
next # keep signal index false
}
keepers[i] <- flag
}
keepers[nrow(df)] <- flag # Set the last element to final flag value
newdf <- df[keepers, ] # subset based on the T/F values determined
keepers这里有一个可能的解决方案,使用data.table
包。我基本上是首先根据状态==1
外观进行分组,然后检查每组是否也有状态==-1
,如果是,我将从第二次事件到-1
事件减去1对组进行细分
library(data.table)
setDT(df)[, indx := cumsum(status == 1)]
df[, if(any(status == -1)) .SD[2:(which(status == -1) - 1)], by = indx]
# indx time status
# 1: 2 4 0
# 2: 2 5 0
# 3: 2 6 0
# 4: 3 10 0
# 5: 3 11 0
# 6: 3 12 0
您是否有更多的数据(或者您是否可以生成更多您知道结果的数据)来查看这/这些是否通用
两种类似的方法:
library(stringr)
df <- data.frame(time = rep(1:14), status = c(0,1,1,0,0,0,-1,0,1,0,0,0,-1,0))
dfr <- rle(df$status)
# first approach
find_seq_str <- function() {
str_locate_all(paste(gsub("-1", "x", dfr$values), collapse=""), "10")[[1]][,2]
}
df[as.vector(sapply(find_seq_str(),
function(n) {
i <- sum(dfr$lengths[1:(n-1)])
tail(i:(i+dfr$lengths[n]), -1)
})),]
# second approach
find_seq_ts <- function() {
which(apply(embed(dfr$values, 2), 1, function(x) all(x == c(0, 1))))
}
df[as.vector(sapply(find_seq_ts(),
function(n) {
i <- sum(dfr$lengths[1:(n)])+1
head(i:(i+dfr$lengths[n+1]), -1)
})),]
库(stringr)
当状态从1变为0,结束信号从0变为-1时,定义df开始信号。因此,在本例中,我希望得到4到6和10到12之间的所有行。@David Arenburg:这与所述问题有关,“当status=1作为开始信号,status=-1作为结束信号时提取所有行”。OP然后在问题下方添加的评论中完全更改了问题。请减少snark。OP想提取1和-1序列之间的所有行,我看得很清楚。@davidernburg:“当status=1作为开始信号,status=-1作为结束信号时,我想提取所有行”字面上要求所有status==1或-1的行。显然这不是他们的意思。正如我已经在上面发布的一样,我正在根据OP重申的问题修改我的代码。现在看起来好多了(+1)
library(stringr)
df <- data.frame(time = rep(1:14), status = c(0,1,1,0,0,0,-1,0,1,0,0,0,-1,0))
dfr <- rle(df$status)
# first approach
find_seq_str <- function() {
str_locate_all(paste(gsub("-1", "x", dfr$values), collapse=""), "10")[[1]][,2]
}
df[as.vector(sapply(find_seq_str(),
function(n) {
i <- sum(dfr$lengths[1:(n-1)])
tail(i:(i+dfr$lengths[n]), -1)
})),]
# second approach
find_seq_ts <- function() {
which(apply(embed(dfr$values, 2), 1, function(x) all(x == c(0, 1))))
}
df[as.vector(sapply(find_seq_ts(),
function(n) {
i <- sum(dfr$lengths[1:(n)])+1
head(i:(i+dfr$lengths[n+1]), -1)
})),]