根据数据框列表中的第N-1行的值,选择第N行。

4
我已经搜索了之前已回答的问题,但还没有构建出一个有效的解决方案。以下是我的情况和演示数据:
假设我让受试者完成一项电脑任务,在每个试验中他们都会作出反应。最终我会得到每个试验的数据,其中包括他们是否给出正确的反应以及他们的反应时间:
sub1 <- data.frame(acc = round(rnorm(10, mean=.65, sd=.25), 0), RT = round(rnorm(10, mean=270, sd=30), 0))
sub2 <- data.frame(acc = round(rnorm(10, mean=.65, sd=.25), 0), RT = round(rnorm(10, mean=270, sd=30), 0))
sub3 <- data.frame(acc = round(rnorm(10, mean=.65, sd=.25), 0), RT = round(rnorm(10, mean=270, sd=30), 0))

sub.list <- list(sub1, sub2, sub3)

我创建了一个列表,其中每个元素都是主题数据。
> sub.list
[[1]]
   acc  RT
1    1 259
2    0 187
3    1 256
4    1 288
5    1 304
6    1 265
7    1 312
8    1 196
9    1 335
10   0 276

[[2]]
   acc  RT
1    1 215
2    0 325
3    1 290
4    0 297
5    0 281
6    1 294
7    0 289
8    1 252
9    0 364
10   0 241

[[3]]
   acc  RT
1    0 292
2    0 267
3    0 240
4    1 321
5    1 292
6    0 269
7    1 241
8    1 206
9    1 250
10   1 283

现在我有一个问题。我想为每个科目创建另一列,该列仅包含由准确响应先前引导的准确试验的RT。下面是一个不工作的for循环和我想要最终结果的示例。

for(i in 1:length(sub.list)){
  for(j in 2:nrow(sub.list[[i]])){
    if(sub.list[[i]][(j-1), "acc"]==1 & sub.list[[i]][j, "acc"]==1){
      sub.list[[i]][j,]$correct.RT <- sub.list[[i]][j, "RT"]
    } else {
      sub.list[[i]][j,]$correct.RT <- NA
    }
  }
}

> sub.list
[[1]]
   acc  RT correctRT
1    1 259        NA
2    0 187        NA
3    1 256        NA
4    1 288       288
5    1 304       304
6    1 265       265
7    1 312       312
8    1 196       196
9    1 335       335
10   0 276        NA

[[2]]
   acc  RT correctRT
1    1 215        NA
2    0 325        NA
3    1 290        NA
4    0 297        NA
5    0 281        NA
6    1 294        NA
7    0 289        NA
8    1 252        NA
9    0 364        NA
10   0 241        NA

[[3]]
   acc  RT correctRT
1    0 292        NA
2    0 267        NA
3    0 240        NA
4    1 321        NA
5    1 292       292
6    0 269        NA
7    1 241        NA
8    1 206       206
9    1 250       250
10   1 283       283

我这么做的原因是为了单独处理这些试验。例如:

> sapply(sub.list, function(x) mean(x$correctRT, na.rm=TRUE))
[1] 283.3333      NaN 257.7500

我知道可以使用mapply或其他apply函数来完成此操作,而不是使用笨拙缓慢的for循环,但我卡在如何引用连续行上。
非常感谢任何帮助!

不太对,当sub.list [N,“acc”] == 0 或者 sub.list [(N-1),“acc”] == 0时,正确的RT应该是NA。希望这样更清楚。我想要的是来自准确率为1的试验的RT,这些试验在错误发生后没有出现(即上一行的准确率为0)。 - YTD
如果您要使用随机样本,请从类似于“set.seed(123)”的内容开始,以使您的数据可重现。 - flodel
抱歉,我不太熟悉在R中生成随机样本,但这非常有用。我将来会学习并使用它。 - YTD
3个回答

4
sub.list <- lapply(sub.list, transform,
                   correctRT = ifelse(acc & c(0, head(acc, -1)), RT, NA))

但是考虑到你的最终目标,我更愿意创建一个标志(TRUE/FALSE)变量:

sub.list <- lapply(sub.list, transform,
                   is.valid = acc & c(0, head(acc, -1)))

那么举个例子,要计算平均值:
sapply(sub.list, with, mean(RT[is.valid]))

+1 如果提到另一个 is.valid 列会很有用。 - Thilo
感谢大家的帮助和建议!我从你们每一个帖子中学到了东西。最终,我决定采用类似于以下方案的方法。 - YTD
1
Hmisc 包有一个 Lag 便利函数,可以替换 c(0, ...) 结构。 - krlmlr
@krlmlr,Hmisc::Lag 会在前面加上 NA,但这对这里来说是不利的。 - flodel

2
你可以使用plyr包中的mutate函数来完成这个任务。
首先,我们需要重新创建数据并设置种子,以确保此示例可重现。
set.seed(123)
sub1 <- data.frame(acc = round(rnorm(10, mean=.65, sd=.25), 0), 
                   RT = round(rnorm(10, mean=270, sd=30), 0))
sub2 <- data.frame(acc = round(rnorm(10, mean=.65, sd=.25), 0), 
                   RT = round(rnorm(10, mean=270, sd=30), 0))
sub3 <- data.frame(acc = round(rnorm(10, mean=.65, sd=.25), 0), 
                   RT = round(rnorm(10, mean=270, sd=30), 0))

sub_list <- list(sub1, sub2, sub3)

现在我们可以将mutate函数应用于您列表中的每个数据框

require(plyr)
lapply(sub_list, mutate, acclag = c(NA, head(acc, -1)), 
                    correctRT = ifelse((acc == 0 | acclag == 0), NA, RT))

## [[1]]
##    acc  RT acclag correctRT
## 1    1 307     NA        NA
## 2    1 281      1       281
## 3    1 282      1       282
## 4    1 273      1       273
## 5    1 253      1       253
## 6    1 324      1       324
## 7    1 285      1       285
## 8    0 211      1        NA
## 9    0 291      0        NA
## 10   1 256      0        NA

## [[2]]
##    acc  RT acclag correctRT
## 1    0 283     NA        NA
## 2    1 261      0        NA
## 3    0 297      1        NA
## 4    0 296      0        NA
## 5    0 295      0        NA
## 6    0 291      0        NA
## 7    1 287      0        NA
## 8    1 268      1       268
## 9    0 261      1        NA
## 10   1 259      0        NA

## [[3]]
##    acc  RT acclag correctRT
## 1    0 278     NA        NA
## 2    1 269      0        NA
## 3    0 269      1        NA
## 4    1 311      0        NA
## 5    1 263      1       263
## 6    0 315      1        NA
## 7    1 224      0        NA
## 8    1 288      1       288
## 9    1 274      1       274
## 10   1 276      1       276

2
lapply(sub.list,
       function(x) {
         a <- x$acc
         # Choose elements which are true, and previous is also true:
         b <- a & c(0, a[-length(a)])
         x$correctRT <- ifelse(b, x$RT, NA)
         x
       })

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接