R: How to filter / smooth the binary signal

I have a binary vector representing a time series. I would like to filter out quick switches, for example, 00000001100000000 should be zeros, and also 11111111111011111 should be only one.

Which filter / function is suitable for this task?

+4
source share
3 answers

Perhaps this is a stupid approach, but rle/ inverse.rleseem to be good candidates. For instance. if you define a quick switch as a period of less than three equal values:

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
+2
source

? 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)))

(, , , , )

+1

Another solution, similar to @sgibb, but using rollapplyfrom the package zoo.

  • Find the trend of the sequence (prevailing value)
  • roll is applied at a fixed window width along the series and accepts the trend if exists with the window.

Easier to explain the code :)

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
+1
source

Source: https://habr.com/ru/post/1532378/


All Articles