Обозначить последовательность элементов строк в фрейме данных (R)

#r #data.table

#r #data.table

Вопрос:

Я работаю с данными отслеживания глаз и пытаюсь создать новый столбец ‘SaccadePerTrial’, который будет подсчитывать (и помечать) появление саккад (ов) в каждом уникальном испытании (игнорируя фиксации (F)).

Вот как выглядит мой фрейм данных в настоящее время:

 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
 

И вот как должен выглядеть столбец ‘saccadeptrial’:

 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
 

Это похоже на функцию rleid(), но я бы хотел, чтобы функция игнорировала значения, которые не являются саккадами. Альтернативным вариантом (хотя и менее предпочтительным) было бы указывать () каждое значение в столбце ‘FixationSaccade’ отдельно (если оба Fs и Ss начинаются с 1).

У кого-нибудь есть идея, как я могу этого добиться? Спасибо!

Ответ №1:

Я бы сделал это так:

 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
 

Или с помощью настраиваемой версии 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
 

Ответ №2:

 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
 

Я считаю magrittr::%>% , что это немного более читабельно, так что то же самое с этим, для стиля:

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