返回R中数据帧行中第一组连续值的列索引

时间:2014-08-14 19:57:27

标签: r dataframe match

我有一个包含月度试用数据的大型数据框(200k行)。每个变量记录该月的试验结果;正(1)或负(0)。该文件还包含唯一ID和许多因子变量,供分析使用。以下是一个简化的示例:

w <- c(101, 0, 0, 0, 1, 1, 1, 5)
x <- c(102, 0, 0, 0, 0, 0, 0, 3)
y <- c(103, 1, 0, 0, 0, 0, 0, 2)
z <- c(104, 1, 1, 1, 0, 0, 0, 2)
dfrm <- data.frame(rbind(w,x,y,z), row.names = NULL)
names(dfrm) <- c("id","jan","feb","mar","apr","may","jun","start")

试用参与者在不同时间加入;最后一列是一个索引,给出该参与者的第一次试验结果记录的列。参与者加入前几个月的结果记录为零(如示例的第一行)。

我想识别每个参与者的三个连续零的第一个序列,然后返回该3个零序列的开始位置;但是,自从他们开始试验以来,我的搜索仅限于列(从索引列开始的那些)。

我的方法 - 我相信还有很多 - 已经把它分成两个任务:在参与者加入之前使用for循环编写NA到那些测试结果:

for (i in 1:nrow(dfrm)){
if(dfrm$start[i] > 2) 
dfrm[i,2:(dfrm$start[i]-1)] <- NA
}

在对全部数据使用匹配循环之前,现在流氓早期零被设置为NA:

for (i in 1:nrow(dfrm)){
f <- match(c(0,0,0), dfrm[i,2:7])
dfrm$outputmth[i] <- f[1]
}

dfrm$outputmth <- dfrm$outputmth - (dfrm$start - 2)

在生成我想要的输出时哪个是成功的(我认为):活动时每个参与者第一次出现3个连续的零,而没有找到任何出现的NA。

这涉及一些笨重的解决方法;特别是第二个循环返回f中3个值的列表,我必须从中选择第一个项来填充dfrm$outputmth.但更重要的是,在完整数据集上运行此代码大约需要30分钟才能执行。所以,感觉有点尴尬,我希望至少有一种更有效的方式来编写和运行它?

非常感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

我认为你所写的内容不应该给出正确的结果......因为match(c(0, 0, 0), ...)将不会匹配前三个连续的零,而是将第一个匹配的零重复三次。通常,您应该尝试避免迭代遍历数据帧行的循环,因为它们往往很慢(例如,如果要更改循环体中数据帧的内容,则会导致创建副本)。解决方法是使用apply遍历数据框的行并使用函数rle检查是否有三个连续的零

dfrm$outputmth <- apply(dfrm[-1], 1, function(x) {
    y <- rle(x[x[7]:6])
    z <- y$values == 0 & y$lengths >= 3
    i <- which(z)[1]
    if (is.na(i)) return(NA)
    if (i == 1) return(x[7])
    return(sum(y$lengths[1:(i-1)]) + x[7])
})

dfrm
#  id jan feb mar apr may jun start outputmth
# 101   0   0   0   1   1   1     5        NA
# 102   0   0   0   0   0   0     3         3
# 103   1   0   0   0   0   0     2         2
# 104   1   1   1   0   0   0     2         4