为了提供一些背景信息,我有一个心理学实验眼动数据的数据框,我想为每个参与者计算两个兴趣区域(AOI)之间的切换。
这是问题的简化数据框(我们假设AOI2 == !AOI1
是不需要的):
library(tidyverse)
df <- tibble(Participant = rep(1:7, times = 1, each = 10),
Time = rep(1:10, 7),
AOI1 = rbinom(70, 1, .5))
我要计算的是AOI1
的值在每个参与者的时间内变化了多少次。我可以使用像波纹管这样的for
循环来做到这一点,但是我想知道是否有一种更简单,更R的方式来做到这一点?
df.switches <- tibble(Participant = 1:7,
Switches = NA)
for(p in 1:7){
s <- 0
for(i in 2:10){
if(subset(df, Participant == p & Time == i, select = AOI1) !=
subset(df, Participant == p & Time == i-1, select = AOI1)){
s <- s + 1
}
}
df.switches <- df.switches %>%
mutate(Switches = ifelse(Participant == p, s, Switches))
}
答案 0 :(得分:4)
一种选择是使用dplyr::lag
将值与当前行进行比较,以便为每个参与者计算开关的数量。
library(tidyverse)
df %>% group_by(Participant) %>%
summarise(count = sum(AOI1 != lag(AOI1, default = -Inf)))
# # A tibble: 7 x 2
# Participant count
# <int> <int>
# 1 1 5
# 2 2 4
# 3 3 5
# 4 4 4
# 5 5 6
# 6 6 6
# 7 7 4
答案 1 :(得分:1)
由于您已经在使用tidyverse
,所以可以使用lag
作为dplyr
的一部分。这将检查AOI1的值是否与先前的值相同,如果不相同,则将标志设置为1。对于每个参与者的第一条记录,该值自动设置为NA
。请注意,group_by
是必需的,否则,每次遇到新的参与者时,该标志都不会“重置”。还假定数据按参与者和时间排序;如果不是,则在arrange(Participant, Time)
之前用管道group_by
。
df <- tibble(Participant = rep(1:7, times = 1, each = 10),
Time = rep(1:10, 7),
AOI1 = rbinom(70, 1, .5))
df2 <- df %>%
group_by(Participant) %>%
mutate(switch = ifelse(AOI1 != lag(AOI1), 1, 0)) %>%
summarise(num_switches = sum(switch, na.rm = TRUE))