Label a sequence of row elements in a dataframe (R)

Viewed 53

I am working with eye-tracking data and I am trying to create a new column 'SaccadePerTrial' which will count (and label) the occurrence of saccades (S) within each unique trial (while ignoring fixations (F)).

This is how my dataframe looks like currently:

Trial | FixationSaccade
1     | F
1     | F
1     | S
1     | S
1     | F
1     | F
1     | S
1     | S

2     | F
2     | F
2     | S
2     | S
2     | F
2     | F
2     | S
2     | S

And this is how the 'SaccadePerTrial' column should look like:

Trial | FixationSaccade | SaccadePerTrial
1     | F               | NA
1     | F               | NA
1     | S               | 1
1     | S               | 1
1     | F               | NA
1     | F               | NA
1     | S               | 2
1     | S               | 2

2     | F               | NA
2     | F               | NA
2     | S               | 1
2     | S               | 1
2     | F               | NA
2     | F               | NA
2     | S               | 2
2     | S               | 2

This is similar to the function rleid(), but I would like the function to ignore values that are not saccades (S). An alternative option (although the less preferred one) would be to rleid() each value in the 'FixationSaccade' column separately (having both the Fs and Ss start from 1).

Does anyone have an idea how I can achieve this? Thank you!

2 Answers
dat[, S := rleid(FixationSaccade == "S"), by=.(Trial) ][
  FixationSaccade == "F", S := NA ][
  , S := (S + (min(S, na.rm = TRUE) == 1L)) / 2L ]
dat
#     Trial FixationSaccade SaccadePerTrial     S
#     <num>          <char>          <char> <num>
#  1:     1               F            <NA>    NA
#  2:     1               F            <NA>    NA
#  3:     1               S               1     1
#  4:     1               S               1     1
#  5:     1               F            <NA>    NA
#  6:     1               F            <NA>    NA
#  7:     1               S               2     2
#  8:     1               S               2     2
#  9:     2               F            <NA>    NA
# 10:     2               F            <NA>    NA
# 11:     2               S               1     1
# 12:     2               S               1     1
# 13:     2               F            <NA>    NA
# 14:     2               F            <NA>    NA
# 15:     2               S               2     2
# 16:     2               S               2     2

I find magrittr::%>% to be a bit more readable, so the same thing with that, for style:

library(magrittr)
dat[, S := rleid(FixationSaccade == "S"), by=.(Trial)] %>%
  .[FixationSaccade == "F", S := NA ] %>%
  .[, S := (S + (min(S, na.rm = TRUE) == 1L)) / 2L ]

I would do it this way:

dat[, newCol := rleid(FixationSaccade), by = .(Trial)]
dat[FixationSaccade == 'F', newCol := NA]
dat[FixationSaccade == 'S', newCol := rleid(newCol), by = .(Trial)]
# > dat
#     Trial FixationSaccade newCol
#  1:     1               F     NA
#  2:     1               F     NA
#  3:     1               S      1
#  4:     1               S      1
#  5:     1               F     NA
#  6:     1               F     NA
#  7:     1               S      2
#  8:     1               S      2
#  9:     2               F     NA
# 10:     2               F     NA
# 11:     2               S      1
# 12:     2               S      1
# 13:     2               F     NA
# 14:     2               F     NA
# 15:     2               S      2
# 16:     2               S      2

Or with a customized version of rleid:

rleid2 <- function(x){
    r <- rle(x)
    y <- cumsum(r$values == 'S')
    y[r$values == 'F'] <- NA
    r$values <- y
    inverse.rle(r)
}
dat[, newCol2 := rleid2(FixationSaccade), by = .(Trial)]

#     Trial FixationSaccade newCol newCol2
#  1:     1               F     NA      NA
#  2:     1               F     NA      NA
#  3:     1               S      1       1
#  4:     1               S      1       1
#  5:     1               F     NA      NA
#  6:     1               F     NA      NA
#  7:     1               S      2       2
#  8:     1               S      2       2
#  9:     2               F     NA      NA
# 10:     2               F     NA      NA
# 11:     2               S      1       1
# 12:     2               S      1       1
# 13:     2               F     NA      NA
# 14:     2               F     NA      NA
# 15:     2               S      2       2
# 16:     2               S      2       2
Related