Ajuste del valor fijo al contar las observaciones

Objetivo: Para crear una variable llamada 'duración'--para contar el número de meses el valor del mes anterior (0 o 1) era consistente, a) sólo cuando hay al menos 3 observaciones consecutivas en el pasado por un mes determinado b) contando como '0' cuando el valor del mes anterior era 1.

Por ejemplo, a muestra estructura de los datos parece:

structure(list(group = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 
2, 2, 2, 2, 2), month = c(2, 4, 5, 6, 7, 10, 11, 12, 13, 14, 
7, 10, 11, 12, 13, 14, 15), value= c(NA, 0, 1, 1, 0, 0, 0, 
0, 0, 0, NA, 1, 1, 0, 0, 0, 1)), class = "data.frame", row.names = c(NA, 
-17L), codepage = 65001L) 

El resultado final parecería (creando la nueva variable, 'duración'):

╔═══════╦═══════╦═══════╦════════════╦═══════════════════════════════════════════════════════════════════════╗
║ group ║ month ║ value ║ 'duration' ║                              explanation                              ║
╠═══════╬═══════╬═══════╬════════════╬═══════════════════════════════════════════════════════════════════════╣
║   1   ║   2   ║   na  ║     na     ║                                                                       ║
╠═══════╬═══════╬═══════╬════════════╬═══════════════════════════════════════════════════════════════════════╣
║   1   ║   4   ║   0   ║     na     ║ There is no consecutive month in the past for this month              ║
╠═══════╬═══════╬═══════╬════════════╬═══════════════════════════════════════════════════════════════════════╣
║   1   ║   5   ║   1   ║     na     ║ There is only 1 consecutive month in the past (4) for this month      ║
╠═══════╬═══════╬═══════╬════════════╬═══════════════════════════════════════════════════════════════════════╣
║   1   ║   6   ║   1   ║     na     ║ There are only 2 consecutive months in the past (5, 6) for this month ║
╠═══════╬═══════╬═══════╬════════════╬═══════════════════════════════════════════════════════════════════════╣
║   1   ║   7   ║   0   ║      0     ║ The previous month's value is 1, so the duration becomes 0            ║
╠═══════╬═══════╬═══════╬════════════╬═══════════════════════════════════════════════════════════════════════╣
║   1   ║   10  ║   0   ║     na     ║ There is no consecutive month in the past for this month              ║
╠═══════╬═══════╬═══════╬════════════╬═══════════════════════════════════════════════════════════════════════╣
║   1   ║   11  ║   0   ║     na     ║ There is only 1 consecutive month in the past (10) for this month     ║
╠═══════╬═══════╬═══════╬════════════╬═══════════════════════════════════════════════════════════════════════╣
║   1   ║   12  ║   0   ║     na     ║ There is only 2 consecutive months in the past (10, 11)               ║
╠═══════╬═══════╬═══════╬════════════╬═══════════════════════════════════════════════════════════════════════╣
║   1   ║   13  ║   0   ║      3     ║ The previous month's (month 12) value (0) is consistent for 3 months  ║
╠═══════╬═══════╬═══════╬════════════╬═══════════════════════════════════════════════════════════════════════╣
║   1   ║   14  ║   0   ║      4     ║ The previous month's (month 13) value (0) is consistent for 4 months  ║
╠═══════╬═══════╬═══════╬════════════╬═══════════════════════════════════════════════════════════════════════╣
║   2   ║   7   ║   na  ║     na     ║                                                                       ║
╠═══════╬═══════╬═══════╬════════════╬═══════════════════════════════════════════════════════════════════════╣
║   2   ║   10  ║   1   ║     na     ║ There is no consecutive month in the past                             ║
╠═══════╬═══════╬═══════╬════════════╬═══════════════════════════════════════════════════════════════════════╣
║   2   ║   11  ║   1   ║     na     ║ There is only 1 consecutive month in the past                         ║
╠═══════╬═══════╬═══════╬════════════╬═══════════════════════════════════════════════════════════════════════╣
║   2   ║   12  ║   0   ║     na     ║ There is only 2 consecutive months in the past                        ║
╠═══════╬═══════╬═══════╬════════════╬═══════════════════════════════════════════════════════════════════════╣
║   2   ║   13  ║   0   ║      1     ║ The previous month's (month 12) value (0) is consistent for 1 month   ║
╠═══════╬═══════╬═══════╬════════════╬═══════════════════════════════════════════════════════════════════════╣
║   2   ║   14  ║   0   ║      2     ║ The previous month's (month 13) value (0) is consistent for 2 months  ║
╠═══════╬═══════╬═══════╬════════════╬═══════════════════════════════════════════════════════════════════════╣
║   2   ║   15  ║   1   ║      3     ║ The previous month's (month 14) value (0) is consistent for 3 months  ║
╚═══════╩═══════╩═══════╩════════════╩═══════════════════════════════════════════════════════════════════════╝

Lo que he intentado aplicar fue (cortesía de @Will):

setDT(sample)
sample[, month_consecutive := NA]
sample[, value_stable_rows := unlist(lapply(sample[, rle(value), by = group]$length, seq))]
sample[, month_consecutive := unlist(lapply(sample[, rle(diffinv(diff(month) != 1)), by = group]$lengths, seq))]
sample[, value_stable_rows := shift(value_stable_rows, type = "lag"), by = group]
sample[, month_consecutive := shift(month_consecutive, type = "lag"), by = group]

sample[, duration := ifelse(value_stable_rows < month_consecutive , value_stable_rows, month_consecutive)]
sample[, month_lag1 := shift(month, n = 1)]
sample[, month_lag2 := shift(month, n = 2)]
sample[, month_lag3 := shift(month, n = 3)]
sample[!((month - month_lag1 == 1) & (month_lag1 - month_lag2 == 1) & (month_lag2 - month_lag3 == 1)), duration := NA]
sample[, .(group, month, value, duration )]

El código anterior se encuentra 'Objetivo a)Pero noObjetivo b)'. Quería preguntar su consejo sobre lo que podría añadirse para poner en marcha la cuenta como '0' cuando el valor del mes anterior era 1.

Pregunta hecha hace 3 años, 4 meses, 29 días - Por codesculptor


3 Respuestas:

  • Para el segundo caso, especificar la expresión lógica en i i.e. check for rows where there is a non-NA in 'duration' and the previous 'value' (shift) es 1, luego asignar 'duración' a 0

    out <- sample[, .(group, month, value, duration )]
    out[!is.na(duration) & shift(value) == 1, duration := 0]
    

    - ¡Fuera!

    out
    #    group month value duration
    # 1:     1     2    NA       NA
    # 2:     1     4     0       NA
    # 3:     1     5     1       NA
    # 4:     1     6     1       NA
    # 5:     1     7     0        0
    # 6:     1    10     0       NA
    # 7:     1    11     0       NA
    # 8:     1    12     0       NA
    # 9:     1    13     0        3
    #10:     1    14     0        4
    #11:     2     7    NA       NA
    #12:     2    10     1       NA
    #13:     2    11     1       NA
    #14:     2    12     0       NA
    #15:     2    13     0        1
    #16:     2    14     0        2
    #17:     2    15     1        3
    

    Respondida el Dec 18, 2020 a las 22:59 - por bytebard

    Votos positivos: 0 | Votos negativos: 0

  • Para lograr el objetivo b) de contar como '0' cuando el valor del mes anterior era 1 en el cálculo de la variable 'duration', puedes modificar ligeramente el código proporcionado. A continuación te muestro una posible manera de hacerlo:

    R
    library(data.table)
    
    

    Creamos un ejemplo de datos

    sample <- structure(list(group = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2), month = c(2, 4, 5, 6, 7, 10, 11, 12, 13, 14, 7, 10, 11, 12, 13, 14, 15), value= c(NA, 0, 1, 1, 0, 0, 0, 0, 0, 0, NA, 1, 1, 0, 0, 0, 1)), class = "data.frame", row.names = c(NA, -17L), codepage = 65001L)

    Convertimos el data.frame a data.table

    setDT(sample)

    Creamos una columna auxiliar para identificar cuando el mes anterior es 1

    sample[, prev_value := shift(value), by = group]

    Calculamos consecutivos y duración

    sample[, month_lag1 := shift(month, n = 1)] sample[, month_diff := month - month_lag1] sample[, consecutivo := cumsum(month_diff == 1), by = group] sample[, duration := ifelse(prev_value == 1, 0, consecutivo)]

    Contar como '0' cuando el valor del mes anterior es 1

    Seleccionamos las columnas requeridas

    result <- sample[, .(group, month, value, duration)]

    Mostramos el resultado

    print(result)

    Con este código, se crea una columna adicional llamada 'prev_value' que representa el valor del mes anterior. Luego, se calcula la duración consecutiva contando como '0' cuando el valor del mes anterior es 1.

    Espero que este ajuste te sea de ayuda. ¡Déjame saber si tienes alguna otra pregunta!

    Respondida el Dec 19, 2020 a las 23:02 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Para ajustar el valor fijo al contar las observaciones y contar como '0' cuando el valor del mes anterior era 1, podemos modificar el código de la siguiente manera:

    
    

    Contabilizar como '0' cuando el valor del mes anterior era 1

    sample[, duration := ifelse(value_stable_rows < month_consecutive & sample[, .(group, month, value, duration )]

    En esta línea, se agrega el término & sample[, month_lag1] == 1 a la condición ifelse. Esto verifica si el valor del mes anterior (almacenado en month_lag1) es 1. Si es 1, el valor de duration se establece en 0, de acuerdo con el requisito.

    El código completo modificado sería:

    
    setDT(sample)
    sample[, month_consecutive := NA]
    sample[, value_stable_rows := unlist(lapply(sample[, rle(value), by = group]$length, seq))]
    sample[, month_consecutive := unlist(lapply(sample[, rle(diffinv(diff(month) != 1)), by = group]$lengths, seq))]
    sample[, value_stable_rows := shift(value_stable_rows, type = "lag"), by = group]
    sample[, month_consecutive := shift(month_consecutive, type = "lag"), by = group]
    
    sample[, duration := ifelse(value_stable_rows < month_consecutive & sample[, month_lag1] == 1, 0, value_stable_rows)]
    sample[, month_lag1 := shift(month, n = 1)]
    sample[, month_lag2 := shift(month, n = 2)]
    sample[, month_lag3 := shift(month, n = 3)]
    sample[!((month - month_lag1 == 1) & (month_lag1 - month_lag2 == 1) & (month_lag2 - month_lag3 == 1)), duration := NA]
    sample[, .(group, month, value, duration )]
    

    Respondida el Dec 19, 2020 a las 23:04 - por Gemini

    Votos positivos: 0 | Votos negativos: 0