2015-10-05 34 views
10

這些都是我的樣本數據:簡單總結,如果表達

dt <- data.table(id=c("a","a","a","a","b","b"), monthsinarrears=c(0,1,0,0,1,0), date=c(2013,2014,2015,2016,2014,2015)) 

表看起來是這樣的:

> dt 
    id monthsinarrears date 
1: a    0 2013 
2: a    1 2014 
3: a    0 2015 
4: a    0 2016 
5: b    1 2014 
6: b    0 2015 

現在我想創建一個名爲「EverinArrears」的附加列將與分配如果id曾經拖欠(歷史),則爲「1」,如果不是,則爲「0」。因此,我想獲得的輸出是:

id monthsinarrears date EverinArrears 
1: a    0 2013    0 
2: a    1 2014    1 
3: a    0 2015    1 
4: a    0 2016    1 
5: b    1 2014    1 
6: b    0 2015    1 

注意貸款ID a是不是歷史上拖欠的2013(這件事發生在2014年),所以這就是爲什麼EverinArrears在2013年

+2

您的結果與您提供的數據不符! –

+0

爲什麼?我只是想根據我提供的第一個表格和我提供的條件來添加這個額外的列EverinArrears。 –

+0

看看你的初始dt,和你寫的東西......這完全不同,即使你的問題是可以理解的) –

回答

14

你可以做以下的(感謝@Roland的提示,以避免數> 1):

dt[, EverinArrears := as.integer(as.logical(cumsum(monthsinarrears))), by=id] 

輸出:

# id monthsinarrears date EA 
#1: a    0 2013 0 
#2: a    1 2014 1 
#3: a    0 2015 1 
#4: a    0 2016 1 
#5: b    1 2014 1 
#6: b    0 2015 1 

注:如果你喜歡短代碼,你也可以做

dt[, EverinArrears := +(!!(cumsum(monthsinarrears))), by=id] 

雖然不是像「良好做法」as.integer(as.logical(...))

正如@Jaap提到的,你也可以這樣做:

dt[, EverinArrears := +(cumsum(monthsinarrears) > 0), by = id] 

,或者更好的做法:

dt[, EverinArrears := as.integer(cumsum(monthsinarrears) > 0), by = id] 

正如評論所說的@Arun ,另一種更簡單的方式:

dt[, EverinArrears := cummax(monthsinarrears), by = id] 
+0

這不起作用是有超過1個月inininrerears每個ID ... –

+0

@ColonelBeauvel權利,良好的捕獲... – Cath

+2

只需包裹'as.logical'。 – Roland

3
得到一個0零以及

您可以使用ave

dt$EverinArrears = as.integer(!!ave(dt$monthsinarrears, dt$id, FUN=cumsum)) 

或者與data.table的好辦法:

dt[, EverinArrears := +(!!cumsum(monthsinarrears)), id][] 
+2

不要在data.table中使用'ave'。這是不必要的緩慢。 – Roland

+0

因爲'!! cumsum()+ 0L'不能用data.table首先使用''ave'解決方案:) –

+1

使用'as.logical'和'as.integer'是更好的做法(更清晰的代碼和邊緣更快)。 – Roland

2

使用包dplyr

library(dplyr) 

dt %>% 
    group_by(id) %>% 
    arrange(date) %>% 
    mutate(EverinArrears = +as.logical(cumsum(monthsinarrears))) %>% 
    data.table 

    id monthsinarrears date EverinArrears 
1: a    0 2013    0 
2: a    1 2014    1 
3: a    0 2015    1 
4: a    0 2016    1 
5: b    1 2014    1 
6: b    0 2015    1 
5

下面是對別人的答案稍有不同:

dt[, newcol := cummax(monthsinarrears > 0), by=id] 

通過使用cummax代替cumsum,我們可以節省一些計算。


下面是對拖欠正月的第一個條目的位置進行比較的方法:

dt[, newcol := { 
    z = which(monthsinarrears > 0) 
    if (!length(z)) rep(0L,.N) 
    else   replace(rep(1L,.N), 1:.N < z[1], 0L) 
}, by=id] 

不知道這可能是任何更有效;它在一定程度上肯定取決於數據。