I have a data frame with a trial column, an index column and a time series (Fy) data column. I would like to use filtfilt() on each trial independently, and the result will be the original data frame with the time series data column filtered.
Example dataset (df):
Trial | Index | Fy |
---|---|---|
1 | 1 | 1.3 |
1 | 2 | 1.4 |
1 | 3 | 1.5 |
1 | 4 | 1.6 |
2 | 5 | 2.4 |
2 | 6 | 2.5 |
2 | 7 | 2.6 |
2 | 8 | 2.7 |
My filter (from the signal package):
bf <- butter(4, 30/(1000/2), type="low")
I can use filtfilt() on a full column like:
df$Fy <- filtfilt(bf, df$Fy)
However, this doesn't allow the filter to recognize that their are different trials in the column, and each trial needs to be filtered seperately.
I have tried:
df %>%
group_by(Trial) %>%
filtfilt(bf, df$Fy) #filters specific data column
And then I tried creating a list of indices by trial:
index <- df %>%
group_by(Trial) %>%
summarise(Indices = paste(sort(unique(Index)), collapse = " "))
And tried lapply for the specific column I'm trying to filter:
df$Fy <- lapply(index, function(x) filtfilt(bf, x))
Here is 1 approach.
library(dplyr)
library(signal)
library(purrr)
df<-tibble::tribble(
~Trial, ~Index, ~Fy,
1L, 1L, 1.3,
1L, 2L, 1.4,
1L, 3L, 1.5,
1L, 4L, 1.6,
2L, 5L, 2.4,
2L, 6L, 2.5,
2L, 7L, 2.6,
2L, 8L, 2.7
)
bf <- butter(4, 30/(1000/2), type="low")
apply_my_filter<-function(df){
df$Fy <- filtfilt(bf, df$Fy)
return(df)
}
df_filtered<-df %>%
group_split(Trial) %>%
map(apply_my_filter) %>%
bind_rows()
df_filtered
#> # A tibble: 8 × 3
#> Trial Index Fy
#> <int> <int> <dbl>
#> 1 1 1 0.0884
#> 2 1 2 0.0777
#> 3 1 3 0.0662
#> 4 1 4 0.0544
#> 5 2 5 0.156
#> 6 2 6 0.137
#> 7 2 7 0.117
#> 8 2 8 0.0962
Created on 2022-01-09 by the reprex package (v2.0.1)