es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Agregue una columna que itere/ cuente cada vez que una secuencia se reinicia.

Tengo un dataframe con una columna que aumenta con cada fila y se reinicia periódicamente (aunque no regularmente) de nuevo a 1. Me gustaría realizar un seguimiento / contar estos reinicios en una columna separada. Este ejemplo de bucle hace exactamente lo que quiero, pero es increíblemente lento cuando se aplica a conjuntos de datos grandes. ¿Existe una mejor / más rápida / más R manera de realizar esta misma operación?

ColA<-seq(1,20)
ColB<-rep(seq(1,5),4)

DF<-data.frame(ColA, ColB)
DF$ColC<-NA

DF[1,'ColC']<-1

#Eliminando la línea 15 y cambiando la línea 5 a 1.1 por comentarios en la respuesta
DF<-DF[-15,]
DF[5,2]<-0.1

for(i in seq(1,nrow(DF)-1)){

  print(i)

  MyRow<-DF[i+1,]

  if(MyRow$ColB < DF[i,'ColB']){
    DF[i+1,"ColC"]<-DF[i,"ColC"] +1
  }else{
    DF[i+1,"ColC"]<-DF[i,"ColC"]
  }
}
Tags:  , ,

Answer

  1. Avatar for davy.ai

    En lugar de usar un ciclo for, puedes utilizar el paquete dplyr de R, que puede ser más eficiente para conjuntos de datos grandes. Aquí tienes un ejemplo de cómo puedes usar dplyr para agregar una nueva columna ColC_reset que cuenta el número de reinicios en ColB:

    biblioteca(dplyr)
    
    DF %>%
      mutate(ColC_reset = ifelse(ColB < lag(ColB, default = first(ColB)), 
                                 cumsum(!is.na(ColC)) + 1, 
                                 cumsum(!is.na(ColC)))) %>%
      na.omit() #eliminar filas con NA en ColC
    

    Lo que hace este código:
    mutate() agrega una nueva columna ColC_reset a DF
    ifelse() verifica si el valor de ColB de cada fila es menor que el valor de ColB de la fila anterior (usando lag(), que desplaza un vector o columna hacia abajo en una posición), lo que indica un reinicio. Si es así, entonces se asigna cumsum(!is.na(ColC)) + 1 a la nueva columna ColC_reset, lo que suma 1 al recuento acumulativo de valores no-NAs en ColC y marca el inicio de un nuevo recuento de reinicios. Si no se cumple la condición de ifelse(), entonces cumsum(!is.na(ColC)) se asigna a ColC_reset, lo que continúa el recuento actual de reinicios.
    na.omit() elimina cualquier fila que tenga NA en la columna ColC (que se crearon en el código original si el valor de ColB de la primera fila fue menor que cualquier otro valor de ColB).

    Esto debería darte el mismo resultado que el ciclo for, pero con mejor rendimiento para conjuntos de datos grandes.

Comments are closed.