R:如何过滤/平滑二进制信号

时间:2014-03-18 22:13:39

标签: r

我有一个表示时间序列的二进制向量。我想过滤出快速开关,如00000001100000000应为零,同样11111111111011111应该只是。

哪种过滤器/功能适合该任务?

3 个答案:

答案 0 :(得分:2)

也许这是一种愚蠢的方法,但rle / inverse.rle似乎是不错的候选人。例如。如果将快速开关定义为小于3个相等值的周期:

b1 <- c(rep(0, 7), rep(1, 2), rep(0, 7))
b2 <- c(rep(1, 10), 0, rep(1, 4))

binaryFilter <- function(x, threshold=3) {
  r <- rle(x)
  isBelowThreshold <- r$lengths < threshold
  r$values[isBelowThreshold] <- abs(1-r$values[isBelowThreshold])
  return(inverse.rle(r))
}

binaryFilter(b1)
# [1] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

binaryFilter(b2)
# [1] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

答案 1 :(得分:1)

如何使用加权平均值考虑邻近值?在这种情况下,考虑每个值的2个邻居(两侧都有2个邻居)。当然这可以调整。

> v <- sample(c(0,1),30,replace=TRUE)

> v
 [1] 0 1 1 1 0 0 0 0 1 1 0 1 0 0 1 0 1 1 0 0 0 0 1 1 1 0 1 0 0 0

# embed(v,5) is a short version for this:
# cbind(v[1:26],v[2:27],v[3:28],v[4:29],v[5:30])

> m <- embed(v,5)

> c(round(m %*% c(.1,.2,.4,.2,.1)))
 [1] 1 1 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 0 1 1 1 0 0 0

before: 0 1 1 1 0 0 0 0 1 1 0 1 0 0 1 0 1 1 0 0 0 0 1 1 1 0 1 0 0 0
after:  . . 1 1 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 0 1 1 1 0 0 0 . .
你可以看到,孤独者已经消失了。


根据sgibb的建议,整个模糊可以归结为:

round(filter(v, c(.1,.2,.4,.2,.1)))

(但我猜上面写出的版本清楚说明了做了什么,这就是为什么我离开它)

答案 2 :(得分:1)

另一种类似于@sgibb解决方案的解决方案,但使用rollapply包中的zoo

  1. 查找序列的趋势(优势值)
  2. 滚动沿着系列以固定的窗口宽度应用,如果窗口存在,则采用趋势。
  3. 更容易通过代码解释:)

    filter_bin <-
    function(vec,width =3){
      trend <- 
        as.numeric(names(which.max(table(vec))))
      rollapply(vec,width,function(x) 
      if(trend %in% x) trend else unique(x))
    }
    
      filter_bin(b2)
      ## 1 1 1 1 1 1 1 1 1 1 1 1 1
      filter_bin(b1)
      ## 0 0 0 0 0 0 0 0 0 0 0 0 0 0