在R中找到长度为n的第一个序列

6
假设我有这样的一个数据框:
df <- data.frame(signal = c(0, 0, 1, 0, 1, 1, 0, 1, 1, 1))

如何通过连续n次进入的第一个信号来找到最佳方法。例如,如果n = 1,则我的信号将是第三个元素,我想得到这样的答案:

c(0, 0, 1, 0, 0, 0, 0, 0, 0, 0)

当n=2时,答案为:
c(0, 0, 0, 0, 0, 1, 0, 0, 0, 0)

当n=3时,最后一个元素是在连续出现3个1之后的信号:

c(0, 0, 0, 0, 0, 0, 0, 0, 0, 1)

2
可以重复吗?也就是说,你可以有 c(0,0,1,0,1,0,1,1,0,1,1,0,1,1,1) 吗? - joran
当然可能会有重复。 - nesvarbu
1
@nesvarbu 对于重复的输出应该是什么样子?最后一个还是所有的都要输出? - rawr
@rawr 好的,这是一个非常好的问题。对我来说,我只需要第一个版本,但由于问题比较普遍,我认为其他版本也会引起其他人的兴趣。 - nesvarbu
3个回答

5
x <- c(0, 0, 1, 0, 1, 1, 0, 1, 1, 1)

y <- rle(x)
y$values <- y$lengths * y$values
(y <- inverse.rle(y))
# [1] 0 0 1 0 2 2 0 3 3 3

f <- function(n) {z <- rep(0, length(y)); z[which.max(cumsum(y == n))] <- 1; z}
f(1)
# [1] 0 0 1 0 0 0 0 0 0 0

f(2)
# [1] 0 0 0 0 0 1 0 0 0 0

f(3)
# [1] 0 0 0 0 0 0 0 0 0 1

完整的功能将是:
g <- function(x, n) {
  y <- rle(x)
  y$values <- y$lengths * y$values
  y <- inverse.rle(y)
  z <- rep_len(0, length(x))
  z[which.max(cumsum(y == n))] <- 1
  z
}
g(x, 1)
g(x, 2)
g(x, 3)

edit version 2

g <- function(x, n, ties = c('first','random','last')) {
  ties <- match.arg(ties)
  FUN <- switch(ties, first = min, last = max,
                random = function(x) x[sample.int(length(x), 1)])
  y <- rle(x)
  y$values <- y$lengths * y$values
  y <- inverse.rle(y)
  z <- rep_len(0, length(x))
  if (!length(wh <- which(y == n)))
    return(z)
  wh <- wh[seq_along(wh) %% n == 0]
  z[FUN(wh)] <- 1
  z
}

x <- c(0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1)

g(x, 1, 'first')
# [1] 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0

g(x, 1, 'last')
# [1] 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0

g(x, 1, 'random')
# [1] 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0

g(x, 4)
# [1] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

5
滚动窗口大小为n的signal的乘积中的第一个1是信号的开始。因此,
f <- function(x, n){
  y <- numeric(length(x))
  k <- RcppRoll::roll_prod(x, n)
  y[which(k==1)[1] + n-1] <- 1
  y
}

> f(df$signal, 1)
 [1] 0 0 1 0 0 0 0 0 0 0
> f(df$signal, 2)
 [1] 0 0 0 0 0 1 0 0 0 0
> f(df$signal, 3)
 [1] 0 0 0 0 0 0 0 0 0 1

合理性检查

set.seed(1)
signal <- sample(0:1, 10, TRUE)
signal
# [1] 0 0 1 1 0 1 1 1 1 0
f(signal, 3)
# [1] 0 0 0 0 0 0 0 1 0 0
g(signal, 3)
# [1] 1 0 0 0 0 0 0 0 0 0
fun(signal, 3)
Error in 1:which(r$len * r$val == n)[1] : NA/NaN argument

3
fun <- function(signal, n) {
  r <- rle(signal == 1)
  replace(numeric(length(signal)), sum(r$l[seq.int(head(which(r$l * r$v == n), 1))]), 1)
}
fun(df$signal, 1)
# [1] 0 0 1 0 0 0 0 0 0 0
fun(df$signal, 2)
# [1] 0 0 0 0 0 1 0 0 0 0
fun(df$signal, 3)
# [1] 0 0 0 0 0 0 0 0 0 1
fun(df$signal, 4)
# [1] 0 0 0 0 0 0 0 0 0 0

如果没有确切的n个1,则会出现错误。 - nesvarbu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接