2014-03-18 63 views
4

我有一個代表時間序列的二進制向量。我想過濾掉像00000001100000000這樣的快速開關應該是零,同樣11111111111011111應該只是一個。R:如何過濾/平滑二進制信號

什麼樣的過濾器/函數適合該任務?

+0

究竟如何定義 '快速切換' 解釋一下嗎? – thumbmunkeys

回答

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

如何使用加權平均值考慮相鄰值?在這種情況下,考慮每個值的兩個鄰居(其兩側都有兩個鄰居)。當然這可以調整。

> 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建議,整個絨毛可以歸結爲:

​​

(但我想上面寫出來的版本清楚什麼做,這就是爲什麼我離開它)

+1

而不是你的'cbind'調用你可以/應該使用'embed'。 – sgibb

+0

@sgibb:好點!謝謝 – Raffael

+2

我想它和'round(filter(v,c(.1,.2,.4,.2,.1)))'完全一樣。 – sgibb

1

另一個類似於從zoo包@sgibb溶液,但使用rollapply溶液。

  1. 找到序列(優勢值)
  2. 輥施加在沿着該系列中的固定窗寬度,並且如果是與窗口存在採取趨勢的趨勢。

簡單的代碼:)

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