superponer - Suma simple si expresión
superponer graficas en r (4)
Aquí hay una ligera variación en las respuestas de los demás:
dt[, newcol := cummax(monthsinarrears > 0), by=id]
Al usar cummax
lugar de cumsum
, podríamos ahorrar en algunos cálculos.
Y aquí hay una manera de comparar con la posición de la primera entrada con meses positivos en mora:
dt[, newcol := {
z = which(monthsinarrears > 0)
if (!length(z)) rep(0L,.N)
else replace(rep(1L,.N), 1:.N < z[1], 0L)
}, by=id]
No estoy seguro si eso podría ser más eficiente; ciertamente depende de los datos hasta cierto punto.
Estos son mis datos de muestra:
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))
La tabla se ve así:
> 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
Ahora quiero crear una columna adicional llamada "EverinArrears" a la que se le asignará "1" si la identificación estaba alguna vez en mora (históricamente) y "0" si no lo era. Por lo tanto, la salida que quiero obtener es:
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
Tenga en cuenta que la identificación del préstamo a
no se encontraba históricamente en Atrasos en 2013 (esto sucedió en 2014), por eso EverinArrears recibe un cero también en 2013.
Puede hacer lo siguiente (gracias a @Roland por la pista para evitar números> 1):
dt[, EverinArrears := as.integer(as.logical(cumsum(monthsinarrears))), by=id]
Salida:
# 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
Nota: si prefiere un código más corto, también puede hacer
dt[, EverinArrears := +(!!(cumsum(monthsinarrears))), by=id]
aunque no es tan "buena práctica" como as.integer(as.logical(...))
Como mencionó @Jaap, también puedes hacer:
dt[, EverinArrears := +(cumsum(monthsinarrears) > 0), by = id]
o, para una mejor práctica:
dt[, EverinArrears := as.integer(cumsum(monthsinarrears) > 0), by = id]
Según lo sugerido por @Arun en el comentario, otra manera más simple:
dt[, EverinArrears := cummax(monthsinarrears), by = id]
Puedes usar ave
:
dt$EverinArrears = as.integer(!!ave(dt$monthsinarrears, dt$id, FUN=cumsum))
O el buen enfoque con data.table:
dt[, EverinArrears := +(!!cumsum(monthsinarrears)), id][]
Usando el paquete 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