3

Consider the following (derived from signal::filter help page):

require(signal)

bf <- butter(5, 0.1) 
t <- seq(0, 1, len = 100)
x <- sin(2*pi*t*2.3) + 0.25*rnorm(length(t)) + 5
y <- filtfilt(bf, x)
z <- filter(bf, x)

plot(t, x, ylim = c(0, max(x)))
lines(t, y, col="red")
lines(t, z, col="blue")
lines(t, stats::filter(x, rep(1/10, 10)), col = "green")
legend("bottomright", legend = c("data", "filtfilt", "filter", "SMA"), 
       pch = 1, col = c("black", "red", "blue", "green"), bty = "n")

exampleFilter

It can be seen that both red and blue (filter and filtfilt, that is) originate in (0,0). However, I would like them to start at a given initial value, such as init = mean(x[1:10]). No matter how I provide said constrain in filter(bf, x), be it integer or vector, I either get no result or length of 'init' must equal length of 'filter'. As a comparison for desired output, a simple moving average (green) is provided. Thank you.

lactea
  • 121
  • 10

1 Answers1

2

To pass an init value for the blue line, this can be achieved by altering 2 lines of your code.

First: store the filter order in a variable, n

bf <- butter(n<-5, 0.1)

and then create an init vector or matrix of correct size

z <- filter(bf, x, init=rep(mean(x[1:10]), n))

enter image description here

As for the red line, filtfilt is a convenience function that actually does not use init, so if you need to set this for the red line, I think you will want to just call the filter method twice yourself, as done in the source, and pass/handle the init value that way. For example:

filtfilt2 <- function(filt, a, x, init)  {
    y = filter(filt, a, c(x, numeric(2 * max(length(a), length(filt)))), init=init)
    y = rev(filter(filt, a, rev(y)))[seq_along(x)]
    y
}
y <- filtfilt2(bf$b, bf$a, x, init=rep(mean(x[1:10]), n))

enter image description here

danielson
  • 1,029
  • 7
  • 8
  • 1
    Thank you. I chose `filtfilt` for getting rid of the phase shift. Using your first example, I have to shift the function manually, say `lines(t[-c((1-10+length(t)):length(t))], z[-c(1:10)], col="blue", lty = "dashed")`. Both `filter`and `filtfilt` make me lose a lot more data in the beginning and end than the SMA. I guess it is in the nature of the filter, though, so I upvoted your neat answer. – lactea Jan 14 '18 at 18:14