简单总和如果表达

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)

  • 只需包装`as.logical`即可. (2认同)
  • `cummax(monthsinarrears)`或`cummax(monthsinarrears> 0L)`也适合这里.. (2认同)

Fra*_*ank 5

这是其他人的答案略有不同:

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)

不确定这可能更有效; 它在某种程度上肯定取决于数据.