2016-08-31 69 views
2

我約4萬行,看起來像個人資料如下:通過其他列有條件補列的值

names <- c("Peter", "Peter", "Peter", "Peter", "Peter", "Peter", "Peter", "Lisa", "Bert", "Carine", "Carine", "Carine", "Carine", "Carine", "Carine") 
luckyToday <- c(0,0,0,NA,0,0,1,NA,1,NA,0,0,0,1,1) 
luckyYesterday <- NA 
df1 <- data.frame(names,luckyToday,luckyYesterday) 

df1 
names luckyToday luckyYesterday 
1 Peter   0    NA 
2 Peter   0    NA 
3 Peter   0    NA 
4 Peter   NA    NA 
5 Peter   0    NA 
6 Peter   0    NA 
7 Peter   1    NA 
8 Lisa   NA    NA 
9 Bert   1    NA 
10 Carine   NA    NA 
11 Carine   0    NA 
12 Carine   0    NA 
13 Carine   0    NA 
14 Carine   1    NA 
15 Carine   1    NA 

數據中包含的人的意見(部分帶1周的觀察,一些帶有更多)和其幸運(1 =幸運,0 =不幸,NA =沒有信息)。作爲一種滯後變量,我想介紹一個新變量(「luckyYesterday」),告訴我在上次觀察期間該人是否幸運。所以,我想要的數據是這樣的:

df2 
names luckyToday luckyYesterday 
1 Peter   0    NA 
2 Peter   0    0 
3 Peter   0    0 
4 Peter   NA    0 
5 Peter   0    0 
6 Peter   0    0 
7 Peter   1    0 
8 Lisa   NA    NA 
9 Bert   1    NA 
10 Carine   NA    NA 
11 Carine   0    0 
12 Carine   0    0 
13 Carine   0    0 
14 Carine   1    0 
15 Carine   1    1 

我知道,R是不適用這樣的數據扯皮完美PROGRAMM,但它是必要的。

我要考慮以下幾點:

  1. 認爲這些都是獨一無二的人我有意見,不要混淆了不同的人的意見。
  2. 較低的觀察值較新。最後一個觀察者是最新的觀察者(第7行是彼得的最新觀察)。
  3. 如果「luckyToday」列中有NA(例如第4行),我不想讓相應的「luckyYesterdayNA」(第5行)填充NA。我寧願讓相應的單元格填充「luckyToday」列中最新的「非NA」觀察值,這是示例數據中的「0」。如果以前的觀察結果只是新生意見,那麼我認爲他們等於最新的觀察結果。 (如果我有9個NAs,第10個觀察值是「1」,那麼我想假設1-9觀察值也是「1」。
  4. 如果每個人只有一個觀察值,我想在「luckyYesterday」專欄,因爲我不知道以前的運氣狀況。

我自己嘗試了2個for-loops,但我在我的數據上花費了很多時間,有超過400萬的觀測值。用更快的解決方案我如用data.table或應用功能,好嗎?我將不勝感激這麼多!

乾杯

回答

2

根據fromLast參數是F還是T,可以使用data.table中的shift函數觀察昨天和na.locf函數從zoo包中填充NA,並且如果您不想混合不同的人的意見:

library(data.table); library(zoo) 
setDT(df1)[,luckyYesterday := shift(na.locf(luckyToday, fromLast = TRUE)), names] 

df1 
#  names luckyToday luckyYesterday 
# 1: Peter   0    NA 
# 2: Peter   0    0 
# 3: Peter   0    0 
# 4: Peter   NA    0 
# 5: Peter   0    0 
# 6: Peter   0    0 
# 7: Peter   1    0 
# 8: Lisa   NA    NA 
# 9: Bert   1    NA 
# 10: Carine   NA    NA 
# 11: Carine   0    0 
# 12: Carine   0    0 
# 13: Carine   0    0 
# 14: Carine   1    0 
# 15: Carine   1    1 
+2

還是一個常見的替代在data.table到na.locf:cumsum與is.na:'DF1 [。N:1,luckyFill:= luckyToday [1L] by =。(names,cumsum(!is.na(luckyToday)))]; df1 [,luckyYest:= shift(luckyFill),by = names] '但是,這需要分組兩次,所以我懷疑na.locf更好。 – Frank

+1

@Frank從未測試過'na.locf'的速度。 'cumsum'通常很快。所以不確定哪一個實際上更快。 – Psidom

2
names <- c("Peter", "Peter", "Peter", "Peter", "Peter", "Peter", 
    "Peter", "Lisa", "Bert", "Carine", "Carine", "Carine", "Carine", "Carine", "Carine") 
luckyToday <- c(0,0,0,NA,0,0,1,NA,1,NA,0,0,0,1,1) 
luckyYesterday <- NA 
df1 <- data.frame(names,luckyToday,luckyYesterday) 

# New code 
library(data.table) 
data.table(df1)[,list(luckyToday, c(NA, luckyToday[1:(.N-1)])),by=list(names)] 
相關問題