Search code examples
rloopsfilterapply

How can I apply a piece of R code to every column of my data frame


I have to analyze EMG data, but I'm not very good in using R: I have a data.frame with 9 columns: one column is specifying the time and the other 8 are specifying my channels. I want to filter my emg data, but I am only able to do it per channel, but I want to do it for all channels of the dataframe at once, so I don't have to apply it to every single channel.

# This example computes the LE-envelope using the lowpass routine

# Coerce a data.frame into an 'emg' object
x <- as.emg(extensor_raw$channel1, samplingrate = 1000, units = "mV")  ##do this for every channel

# Compute the rectified signal
x_rect <- rectification(x)

# Filter the rectified signal
y <- lowpass(x_rect, cutoff = 100)

# change graphical parameters to show multiple plots
op <- par(mfrow = c(3, 1))

# plot the original channel, the filtered channel and the 
# LE-envelope
plot(x, channel = 1, main = "Original  channel")
plot(x_rect, main = "Rectified  channel")
plot(y, main = "LE-envelope")

# reset graphical parameters
par(op)

so instead of using extensor_raw$channel1 here can i put something in like extensor_raw$i and loop around it? Or is there any way to apply this bit of code to every channel (i.e. 8 column of the 9 column data frame excluding the first column which specified the time?)


Solution

  • Here my solution. First of all, as there is no data with your question I used the 'EMG data for gestures Data Set' from UCI Machine Learning Repository.

    Link https://archive.ics.uci.edu/ml/datasets/EMG+data+for+gestures

    It is fairly similar dataset you been using, first variable is time and after that 8 variables are channels, the last one is class

    enter image description here

    To create a graph for every channel you can use FOR loop by using the column of your concern as your iterating operator. Middle code is same as yours, at last while plotting I did the change in plot title so it resembles with its respective column name.

    library(biosignalEMG)
    
    extensor_raw <- read.delim("01/1_raw_data_13-12_22.03.16.txt")
    head(extensor_raw)
    
    for(i in names(extensor_raw[2:9])){
      print(paste("Drawing for ", i))
      # Coerce a data.frame into an 'emg' object
      x <- as.emg(extensor_raw[i], samplingrate = 1000, units = "mV")  ##do this for every channel
      
      # Compute the rectified signal
      x_rect <- rectification(x)
      
      # Filter the rectified signal
      y <- lowpass(x_rect, cutoff = 100)
      
      # change graphical parameters to show multiple plots
      op <- par(mfrow = c(3, 1))
      
      # plot the original channel, the filtered channel and the 
      # LE-envelope
      plot(x, channel = 1, main = paste("Original ", i))
      plot(x_rect, main = paste("Rectified", i))
      plot(y, main = paste("LE-envelope", i))
      
    }
    

    At the end of this code you can see multiple pages created in graph section of rstudio, plotting each channel from 1 to 8 simultaneously

    like for channel 5 and similarly for others. I hope this should help you to resolve your problem.

    enter image description here

    On the second part you have asked in comments : If you have the files separate let's keep it separate. will read it one by one and then plot it. To achieve this we will use nested FOR loop. First set up your working directory, where you have all your gesture files. Like here in my case I have two files in my directory with same structure.

    enter image description here

    The changes in the code is as follows :

    setwd('~/Downloads/EMG_data_for_gestures-master/01')
    library(biosignalEMG)
    
    for(j in list.files()){
      print(paste("reading file ",j))
      extensor_raw <- read.delim(j)
      head(extensor_raw)
      
      for(i in names(extensor_raw[2:9])){
        print(paste("Drawing for ", i))
        # Coerce a data.frame into an 'emg' object
        x <- as.emg(extensor_raw[i], samplingrate = 1000, units = "mV")  ##do this for every channel
        
        # Compute the rectified signal
        x_rect <- rectification(x)
        
        # Filter the rectified signal
        y <- lowpass(x_rect, cutoff = 100)
        
        # change graphical parameters to show multiple plots
        op <- par(mfrow = c(3, 1))
        
        # plot the original channel, the filtered channel and the LE-envelope
        
        plot(x, channel = 1, main = paste("Original ", i," from ", j))
        plot(x_rect, main = paste("Rectified", i," from ", j))
        plot(y, main = paste("LE-envelope", i," from ", j))
        
      }
    }
    

    I hope this will be helpful.