0

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))
mkp
  • 51
  • 6
  • 1
    With no idea of your input data nor you expected result and merely a description of the problem of “doesn’t work well”, it’s going to be difficult to help you. Please read the copious advice that’s available on how to ask a good question and then update your post. – Limey Jan 08 '22 at 17:29
  • What is filtfilt? [See here](https://stackoverflow.com/q/5963269/5325862) on making a reproducible example that is easier for folks to help with. – camille Jan 08 '22 at 20:04
  • Thank you for the feedback, I've made edits to clarify. Please let me know of other questions. – mkp Jan 08 '22 at 20:38

1 Answers1

0

Here is 1 approach.

  1. Break the dataframe into a list of dataframes by group using group_split.
  2. Map each dataframe using map from the purrr package.
  3. Bind the rows back into a normal dataframe.
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)

Joe Erinjeri
  • 1,200
  • 1
  • 7
  • 15