Reputation: 21400
I have pupillary data, with Diam_av
recording averaged pupil diameter, like so:
df <- data.frame(
Diam_av = c(12.3,13,15.5,0,0,0,0,13.7,0,0,9.98,4,0,8.76)
)
Sometimes Diam_av
is 0
. I assume there to be a blink (i.e., eyes closed) where there are at least 4 consecutive 0
values. I'm trying to flag
these Blinks
, thus:
library(dplyr)
df %>%
mutate(Blinks = ifelse(Diam_av == 0 & lag(Diam_av) == 0 & lag(Diam_av, 2) == 0 & lag(Diam_av, 3) == 0,
"yes", "no"),
Blinks = ifelse(lead(Blinks) == "yes"|lead(Blinks,2) == "yes"|lead(Blinks,3) == "yes",
"yes", Blinks))
1 12.30 no
2 13.00 no
3 15.50 no
4 0.00 yes
5 0.00 yes
6 0.00 yes
7 0.00 yes
8 13.70 no
9 0.00 no
10 0.00 no
11 9.98 no
12 4.00 <NA>
13 0.00 <NA>
14 8.76 <NA>
While the result is acceptable in terms of Blinks
detection, there are two issues with the code: (i) it seems bulky and repetitive and (ii) some Blinks
get changed to NA
whereas they should be no
. How can the code be mended?
Upvotes: 1
Views: 51
Reputation: 887251
Using data.table
library(data.table)
setDT(df)[, Blinks := c('no', 'yes')[1 + (.N >= 4)],rleid(Diam_av == 0)]
df
Diam_av Blinks
1: 12.30 no
2: 13.00 no
3: 15.50 no
4: 0.00 yes
5: 0.00 yes
6: 0.00 yes
7: 0.00 yes
8: 13.70 no
9: 0.00 no
10: 0.00 no
11: 9.98 no
12: 4.00 no
13: 0.00 no
14: 8.76 no
Upvotes: 1
Reputation: 389055
You may use rle
and change 4 consecutive 0 values to 'yes'
and rest of them as 'no'
.
library(dplyr)
df %>%
mutate(Blinks = ifelse(with(rle(Diam_av == 0),
rep(values & lengths >= 4, lengths)), 'yes', 'no'))
# Diam_av Blinks
#1 12.30 no
#2 13.00 no
#3 15.50 no
#4 0.00 yes
#5 0.00 yes
#6 0.00 yes
#7 0.00 yes
#8 13.70 no
#9 0.00 no
#10 0.00 no
#11 9.98 no
#12 4.00 no
#13 0.00 no
#14 8.76 no
Upvotes: 2