2017-03-08 217 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