2017-03-08 68 views
0

我有一些35,000行。如果preventtive_chem值为“Y”,则prev_efficacy的值在过去3天为5,3,1,在下一周为10到1。样例输出在img文件中。R for循环,为新变量赋值增量值

Prev_Chem Date prev_effi 
0 7/3/2016 0 
0 7/4/2016 0 
0 7/5/2016 1 
0 7/6/2016 3 
Y 7/7/2016 5 
0 7/8/2016 10 
0 7/9/2016 9 
0 7/10/2016 8 
0 7/11/2016 7 
0 7/12/2016 6 
0 7/13/2016 5 
0 7/14/2016 4 
0 7/15/2016 3 
0 7/16/2016 2 
0 7/17/2016 1 
0 7/18/2016 0 
0 7/19/2016 0 

如果preventive_chem值为0,则prev_efficacy值为0

当我尝试这个代码,

*df$PreventEffic <- rep(0,nrow(df)) 
for(i in 1:nrow(df)) 
    { 
    if(df$Preventive_Chem1[i] == "Y") 
     { 
     df$PreventEffic[i] <- 5 
     df$PreventEffic[i-2] <- 1 
     df$PreventEffic[i-1] <- 3 
     df$PreventEffic[i+1] <- 10 
     df$PreventEffic[i+2] <- 9 
     df$PreventEffic[i+3] <- 8 
     df$PreventEffic[i+4] <- 7 
     df$PreventEffic[i+5] <- 6 
     df$PreventEffic[i+6] <- 5 
     df$PreventEffic[i+7] <- 4 
     df$PreventEffic[i+8] <- 3 
     df$PreventEffic[i+9] <- 2 
     df$PreventEffic[i+10] <- 1 
     } 
    }* 

这将需要大量的时间来运行代码和返回值0到1016321行。有没有有效的方法来处理这个问题,而不使用“for循环”。

+0

将来,请始终输入您的样本数据,例如'dput(df)',这样我们就可以复制和粘贴你的数据,但在这之前,请修复与命名约定不一致的地方 - 为什么你的if语句中df的colname不同? 'Prev_Chem'与'Preventive_Chem1'。我在下面提供解决方案。 – Djork

+0

我们是否需要考虑数字分配之间的任何重叠?也就是说,是否会有Prev_Chem的+10和-3范围内出现2个Y的事件? – JPHwang

+0

Teenu Ss,我强烈建议你接受@ R.S.的回答,但考虑一下'Y'的晚期角落案例,作为我的回答和评论。 – r2evans

回答

2

假设您的数据框架结构是一致的 - 即在Y出现之前2天和之后10天,那么您不需要for循环,只需找到“Y”的索引并使用这种分配值为每个+/-天:

indx <- which(df$Prev_Chem == "Y") 
df$PreventEffic <- rep(0,nrow(df)) 
df$PreventEffic[indx] <- 5 
df$PreventEffic[indx-2] <- 1 
df$PreventEffic[indx-1] <- 3 
df$PreventEffic[indx+1] <- 10 
df$PreventEffic[indx+2] <- 9 
df$PreventEffic[indx+3] <- 8 
df$PreventEffic[indx+4] <- 7 
df$PreventEffic[indx+5] <- 6 
df$PreventEffic[indx+6] <- 5 
df$PreventEffic[indx+7] <- 4 
df$PreventEffic[indx+8] <- 3 
df$PreventEffic[indx+9] <- 2 
df$PreventEffic[indx+10] <- 1 
+0

非常感谢R.s !!!!!!!!!你的代码帮助我堆......我注意到你的dput点(df)......下次会这么做。此外,命名消歧发生在我的懒惰和空间限制那里。我有一个疑问。当我执行代码时,将“值0”返回到PreventEffic列中的1016321行,尽管我只有35,000行。如何纠正它...非常感谢。 –

+0

您能否提供您运行的确切代码以重新引用“值0”? – Djork

+0

嗨R.s.我很抱歉,因为我在数据框中选择行时犯了一个错误。感谢您的解决方案。帮助我很多....现在没有错误... –

1

主要低效的两个在你的代码:

  1. 预先计算,其中有趣的纵向上,一次全部。而不是逐行循环,只需做矢量化比较。

  2. 由于您正在将一个固定的数字向量分配给紧邻每个匹配行周围的位置,您也可以在向量中进行赋值。

第一切割(但不适用ï阳离子)实现可以是:

n <- 32 
df <- data.frame(x = rep(0, n), y = 0) 
df$x[c(5,20)] <- 1 
str(df) 
# 'data.frame': 32 obs. of 2 variables: 
# $ x: num 0 0 0 0 1 0 0 0 0 0 ... 
# $ y: num 0 0 0 0 0 0 0 0 0 0 ... 

for (i in which(df$x == 1)) 
    df$y[i + -2:10] <- c(1,3,5,10:1) 
df 
# x y 
# 1 0 0 
# 2 0 0 
# 3 0 1 
# 4 0 3 
# 5 1 5 
# 6 0 10 
# 7 0 9 
# 8 0 8 
# 9 0 7 
# 10 0 6 
# 11 0 5 
# 12 0 4 
# 13 0 3 
# 14 0 2 
# 15 0 1 
# 16 0 0 
# 17 0 0 
# 18 0 1 
# 19 0 3 
# 20 1 5 
# 21 0 10 
# 22 0 9 
# 23 0 8 
# 24 0 7 
# 25 0 6 
# 26 0 5 
# 27 0 4 
# 28 0 3 
# 29 0 2 
# 30 0 1 
# 31 0 0 
# 32 0 0 

但应该很快知道,当有东西比10行不感兴趣的的底部会发生什么data.frame。也就是说,你可能会看到类似的错误:

# Error in `$<-.data.frame`(`*tmp*`, "y", value = c(0, 0, 1, 3, 5, 10, 9, : 
# replacement has 30 rows, data has 28 

那么你可以试试这个(请原谅的罪恶变量命名):

for (i in which(df$x == 1)) { 
    j <- c(-2:0, head(1:10, n = dfn - i)) 
    k <- c(1,3,5, head(10:1, n = dfn - i)) 
    df$y[i + j] <- k 
} 

head(..., n=dfn-i)就是确保我们永远不会有更多的替换数据比我们预先存在的行要修改。

+0

@ R.S.的答案比我的答案有优势,但如果你不小心,它会成为“行数太少”的牺牲品。有办法缓解这种情况,仍然使用他的解决方案。要真正知道,你需要一个基准。要做到这一点,您需要比我选择在此使用的实际数据或更具代表性的数据。我的猜测是,其他答案将是一个或两个比这更快... – r2evans

+0

好! Y之后没有假设事件存在的解决方案!在同一时间发表评论,但是,我提供的解决方案是对数据结构的假设。 – Djork

+1

最好的解决方案可能是使用你的答案,除了那些发生在最后10行(即,过滤掉'indx>(nrow(df)-10)',然后使用我的'头的变体(.. )''技巧对于那些。 – r2evans