Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/79.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R 如何提取起始信号和结束信号之间的所有行?_R_Dataframe_Filtering - Fatal编程技术网

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)
  })),]