根据先前值更改变量值

时间:2016-06-29 11:49:21

标签: r replace conditional

我有以下数据集:

df <- data.frame(subject = c(1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3), 
             time = c(1,2,3,4,5,6,7,8,9,10,11,12,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,11), 
             performance = c(1,0,-1,-1,0,1,1,-1,0,0,0,1,1,1,-1,0,1,1,-1,0,0,1,-1,1,1,0,1,1,-1,0,-1,-1,0))

我想要做的是更改性能变量中的一些条目。更具体地说,如果“-1”条目前面有“1”,我想将“-1”改为“0”。

然而,这应该仅在受试者内进行,而不是在受试者之间进行(所有受试者都有不同数量的会话)。

所以,这就是我最终想要的:

 df2 =data.frame(subject = c(1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3), 
                        time = c(1,2,3,4,5,6,7,8,9,10,11,12,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,11), 
                        performance = c(1,0,-1,-1,0,1,1,0,0,0,0,1,1,1,0,0,1,1,0,0,0,1,-1,1,1,0,1,1,-1,0,-1,-1,0))

有谁知道如何做到这一点?

提前致谢! S上。

4 个答案:

答案 0 :(得分:2)

使用dplyr

df %>% 
  group_by(subject) %>% 
  mutate(performance = replace(performance, which(performance + lag(performance)==0 & performance == -1), 0))

答案 1 :(得分:1)

这是一个data.table方法,我首先创建一个flag列,然后用于对数据进行子集化并通过引用更新performance列。

library(data.table)
dt <- as.data.table(df) # or setDT(df)
dt[, flag := performance == -1 & shift(performance, 1L) == 1, by = subject]
dt[(flag), performance := 0][, flag := NULL]

我选择使用中间标志列来完成它,因为我希望它能够很好地处理大型数据集。如果您不关心效果,则可以使用ifelsereplace代替。

答案 2 :(得分:0)

这很难看,但应该有效:

dftest <- df
for (i in 2:nrow(dftest)) {
  if(
    dftest$performance[i] == -1 && dftest$performance[i - 1] == 1
  ){
    if(
      dftest$subject[i] == dftest$subject[i - 1]
    ) {
      dftest$performance[i] <- 0
    }
 }
}

all.equal(df2, dftest) # ONE ERROR

这在第29行给出了错误 - 你能在这里检查你的示例df2是否正确吗?如果我理解正确的问题df2$performance[29]应为0

答案 3 :(得分:0)

使用bysapply的基础R解决方案:

gr <- do.call(c, by(df, df$subject, function(x) {
c(FALSE, unlist(sapply(1:length(x$performance), 
function(y) (x$performance[y] == -1) & (x$performance[y-1] == 1))))
}))
df[gr, 3] <- 0
cbind(df, df2)