2016-01-18 77 views
0

尋找一種方法來填充一個向量,其中新值的條件是該向量中的值和數據框中的另一個變量。粘貼下面的數據的例子。條件系列填充R

PrsVar= c(rep(1,10),rep(2,7),rep(3,11)) 
IndVar = c(0,0,0,1,0,0,1,0,0,0,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0) 
OutVar = c(1,1,1,1,2,2,2,3,3,3,1,1,1,1,2,2,2,1,1,1,1,2,2,2,2,3,3,3) 
exampdata <- cbind(PrsVar,IndVar,OutVar) 
exampdata <- as.data.frame(exampdata) 

> exampdata 
    PrsVar IndVar OutVar 
1  1  0  1 
2  1  0  1 
3  1  0  1 
4  1  1  1 
5  1  0  2 
6  1  0  2 
7  1  1  2 
8  1  0  3 
9  1  0  3 
10  1  0  3 
11  2  0  1 
12  2  0  1 
13  2  0  1 
14  2  1  1 
15  2  0  2 
16  2  0  2 
17  2  1  2 
18  3  0  1 
19  3  0  1 
20  3  0  1 
21  3  1  1 
22  3  0  2 
23  3  0  2 
24  3  0  2 
25  3  1  2 
26  3  0  3 
27  3  0  3 
28  3  0  3 

這是時間序列數據,每行代表一個人日。 PrsVar是研究中個人的ID,IndVar表示該人物節結束於該人日。之後的人日代表了新的一集。

我想使用PrsVarIndVar的值創建一個類似OutVar的變量。這個新變量OutVar標記每個人每天所處的情節,遞增1,並且從每個新個體開始1。

我可以通過一個循環來運行它,但我需要更高效的代碼來處理3,000,000多行數據。試圖在dplyrmapply中使用某些東西,但我很難過。想想解決這個問題會對其他人有所幫助,並且在不久的將來肯定會對我有所幫助。

回答

1

有點難看,但這種邏輯應該是很容易適應其他方法:

with(exampdata, 
    ave(IndVar, PrsVar, FUN=function(x) { 
    out <- rev(cumsum(rev(x))) 
    max(out) - out + 1 
    }) 
) 

# [1] 1 1 1 1 2 2 2 3 3 3 1 1 1 1 2 2 2 1 1 1 1 2 2 2 2 3 3 3 
+0

謝謝,我結束了這個使用。沒有考慮反向,反向,非常有幫助。 – ArcherT

3

data.table包提供了一個快速,高效,整潔的方式做到這一點。這一切都是通過引用完成的(不是通過值,所以沒有複製完成),所以數百萬行根本不會成爲問題(也許不到一分鐘)。

library(data.table) 
patient.data <- data.table(PrsVar = c(rep(1,10), rep(2,7), rep(3,11)), 
          IndVar = c(0,0,0,1,0,0,1,0,0,0,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0), 
          OutVar = c(1,1,1,1,2,2,2,3,3,3,1,1,1,1,2,2,2,1,1,1,1,2,2,2,2,3,3,3)) 

增量情節的基礎上IndVar(加1)的累積和計數器EpVar。這增加了IndVar增加的記錄處的計數器(這爲時過早),因此將其向shift下移記錄,用復位計數器(1)替換缺失的值。這可以通過by關鍵字進行分組。

patient.data[ , EpVar:=shift(1+cumsum(IndVar), fill=1), by=PrsVar] 
patient.data 
    PrsVar IndVar OutVar EpVar 
1:  1  0  1  1 
2:  1  0  1  1 
3:  1  0  1  1 
4:  1  1  1  1 
5:  1  0  2  2 
6:  1  0  2  2 
7:  1  1  2  2 
8:  1  0  3  3 
9:  1  0  3  3 
10:  1  0  3  3 
11:  2  0  1  1 
12:  2  0  1  1 
13:  2  0  1  1 
14:  2  1  1  1 
15:  2  0  2  2 
16:  2  0  2  2 
17:  2  1  2  2 
18:  3  0  1  1 
19:  3  0  1  1 
20:  3  0  1  1 
21:  3  1  1  1 
22:  3  0  2  2 
23:  3  0  2  2 
24:  3  0  2  2 
25:  3  1  2  2 
26:  3  0  3  3 
27:  3  0  3  3 
28:  3  0  3  3 
+0

謝謝,我一直在考慮使用data.table,但沒有時間進入它,並且數據幀上的dplyr一直很順利。 – ArcherT

+0

如果您想要學習'data.table',那麼DataCamp課程結構良好。 'dplyr'也適用於data.tables。由複製引用引起的速度改進非常突出,並且在使用數百萬行時可能是必需的。 我答案的'data.frame'版本上的'dplyr'仍然需要'data.table :: shift()',但差不多相同; 'library(dplyr); data.frame(patient.data)%>%group_by(PrsVar)%> mutate(EpVar = shift(1 + cumsum(IndVar),fill = 1))' –