Author: Tristan Mahr
Date: 2025-04-25

# Working with multiple files

#### Tristan Mahr

#### 2025-04-25

Suppose we want to load all the Eprime files in a directory and combine the results in dataframe.

My strategy in this scenario is to figure out what I need to do for a single file and then wrap those steps in a function that takes a filepath to a txt file and returns a dataframe. After some exploration and interactive programming, I come up with the following function.

    library("plyr")
    reduce_sails <- function(sails_path) {
      sails_lines <- read_eprime(sails_path)
      sails_frames <- FrameList(sails_lines)

      # Trials occur at level 3
      sails_frames <- keep_levels(sails_frames, 3)
      sails <- to_data_frame(sails_frames)

      # Tidy up
      to_pick <- c("Eprime.Basename", "Running", "Module", "Sound",
                   "Sample", "Correct", "Response")
      sails <- sails[to_pick]
      running_map <- c(TrialLists = "Trial", PracticeBlock = "Practice")
      sails$Running <- running_map[sails$Running]

      # Renumber trials in the practice and experimental blocks separately.
      # Numerically code correct response.
      sails <- ddply(sails, .(Running), mutate,
                     TrialNumber = seq(from = 1, to = length(Running)),
                     CorrectResponse = ifelse(Correct == Response, 1, 0))
      sails$Sample <- NULL

      # Optionally, one might save the processed file via:
      # csv <- paste0(file_path_sans_ext(sails_path), ".csv")
      # write.csv(sails, csv, row.names = FALSE)
      sails
    }

Here’s a preview of what the function returns when given a filepath.

    head(reduce_sails("data/SAILS/SAILS_001X00XS1.txt"))
    #>   Eprime.Basename  Running Module     Sound Correct Response TrialNumber
    #> 1 SAILS_001X00XS1 Practice   LAKE LAKE1.WAV    Word     Word           1
    #> 2 SAILS_001X00XS1 Practice   LAKE  MAKE.WAV NotWord  NotWord           2
    #> 3 SAILS_001X00XS1 Practice   LAKE LAKE1.WAV    Word     Word           3
    #> 4 SAILS_001X00XS1 Practice   LAKE LAKE1.WAV    Word     Word           4
    #> 5 SAILS_001X00XS1 Practice   LAKE  MAKE.WAV NotWord  NotWord           5
    #> 6 SAILS_001X00XS1 Practice   LAKE LAKE1.WAV    Word     Word           6
    #>   CorrectResponse
    #> 1               1
    #> 2               1
    #> 3               1
    #> 4               1
    #> 5               1
    #> 6               1

Now that the function works on one file, I can use `ldply` to apply the function to several files, returning results in a single dataframe. (For `dplyr`, I would `lapply` the function to each path to get a list of dataframes, then use `bind_rows` to combine into a single dataframe.)

    sails_paths <- list.files("data/SAILS/", pattern = ".txt", full.names = TRUE)
    sails_paths
    #> [1] "data/SAILS/SAILS_001X00XS1.txt" "data/SAILS/SAILS_002X00XS1.txt"
    ensemble <- ldply(sails_paths, reduce_sails)

Finally, with all of the subjects’ data contained in a single dataframe, I can use `ddply` plus `summarise` and compute summary scores at different levels of aggregation within each subject.

    # Score trials within subjects
    overall <- ddply(ensemble, .(Eprime.Basename, Running), summarise,
                     Score = sum(CorrectResponse),
                     PropCorrect = Score / length(CorrectResponse))
    overall
    #>   Eprime.Basename  Running Score PropCorrect
    #> 1 SAILS_001X00XS1 Practice    10   1.0000000
    #> 2 SAILS_001X00XS1    Trial    61   0.8714286
    #> 3 SAILS_002X00XS1 Practice     9   0.9000000
    #> 4 SAILS_002X00XS1    Trial    57   0.8142857

    # Score modules within subjects
    modules <- ddply(ensemble, .(Eprime.Basename, Running, Module), summarise,
                     Score = sum(CorrectResponse),
                     PropCorrect = mean(CorrectResponse))
    modules
    #>    Eprime.Basename  Running Module Score PropCorrect
    #> 1  SAILS_001X00XS1 Practice   LAKE    10   1.0000000
    #> 2  SAILS_001X00XS1    Trial    CAT     9   0.9000000
    #> 3  SAILS_001X00XS1    Trial   LAKE    10   1.0000000
    #> 4  SAILS_001X00XS1    Trial    RAT    16   0.8000000
    #> 5  SAILS_001X00XS1    Trial    SUE    26   0.8666667
    #> 6  SAILS_002X00XS1 Practice   LAKE     9   0.9000000
    #> 7  SAILS_002X00XS1    Trial    CAT     8   0.8000000
    #> 8  SAILS_002X00XS1    Trial   LAKE    10   1.0000000
    #> 9  SAILS_002X00XS1    Trial    RAT    11   0.5500000
    #> 10 SAILS_002X00XS1    Trial    SUE    28   0.9333333