Dav*_*cht 10 conditional r sum data.table
这些是我的样本数据:
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))
Run Code Online (Sandbox Code Playgroud)
该表如下所示:
> 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
Run Code Online (Sandbox Code Playgroud)
现在我想创建一个名为"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
Run Code Online (Sandbox Code Playgroud)
请注意,贷款ID a在2013年的历史上并非拖欠(这发生在2014年),因此EverinArrears在2013年也获得0零.
Cat*_*ath 14
您可以执行以下操作(感谢@Roland提示,以避免数字> 1):
dt[, EverinArrears := as.integer(as.logical(cumsum(monthsinarrears))), by=id]
Run Code Online (Sandbox Code Playgroud)
输出:
# 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
Run Code Online (Sandbox Code Playgroud)
注意:如果您更喜欢更短的代码,您也可以这样做
dt[, EverinArrears := +(!!(cumsum(monthsinarrears))), by=id]
Run Code Online (Sandbox Code Playgroud)
虽然不像"好习惯"那样 as.integer(as.logical(...))
正如@Jaap所提到的,你也可以这样做:
dt[, EverinArrears := +(cumsum(monthsinarrears) > 0), by = id]
Run Code Online (Sandbox Code Playgroud)
或者,为了更好的实践:
dt[, EverinArrears := as.integer(cumsum(monthsinarrears) > 0), by = id]
Run Code Online (Sandbox Code Playgroud)
正如@Arun在评论中所建议的那样,另一种更简单的方式:
dt[, EverinArrears := cummax(monthsinarrears), by = id]
Run Code Online (Sandbox Code Playgroud)
这是其他人的答案略有不同:
dt[, newcol := cummax(monthsinarrears > 0), by=id]
Run Code Online (Sandbox Code Playgroud)
通过使用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]
Run Code Online (Sandbox Code Playgroud)
不确定这可能更有效; 它在某种程度上肯定取决于数据.