Crea contatore con più variabili

Ho i miei dati che assomigliano di seguito:

CustomerID TripDate 1 1/3/2013 1 1/4/2013 1 1/9/2013 2 2/1/2013 2 2/4/2013 3 1/2/2013 

Devo creare una variabile contatore, che sarà come di seguito:

 CustomerID TripDate TripCounter 1 1/3/2013 1 1 1/4/2013 2 1 1/9/2013 3 2 2/1/2013 1 2 2/4/2013 2 3 1/2/2013 1 

Tripcounter sarà per ogni cliente.

Usa ave Supponendo che il tuo data.frame si chiami “mydf”:

 mydf$counter <- with(mydf, ave(CustomerID, CustomerID, FUN = seq_along)) mydf # CustomerID TripDate counter # 1 1 1/3/2013 1 # 2 1 1/4/2013 2 # 3 1 1/9/2013 3 # 4 2 2/1/2013 1 # 5 2 2/4/2013 2 # 6 3 1/2/2013 1 

Per quello che vale, ho anche implementato una versione di questo approccio in una funzione inclusa nel mio pacchetto "splitstackshape". La funzione è chiamata getanID :

 mydf <- data.frame(IDA = c("a", "a", "a", "b", "b", "b", "b"), IDB = c(1, 2, 1, 1, 2, 2, 2), values = 1:7) mydf # install.packages("splitstackshape") library(splitstackshape) # getanID(mydf, id.vars = c("IDA", "IDB")) getanID(mydf, id.vars = 1:2) # IDA IDB values .id # 1 a 1 1 1 # 2 a 2 2 1 # 3 a 1 3 2 # 4 b 1 4 1 # 5 b 2 5 1 # 6 b 2 6 2 # 7 b 2 7 3 

Come puoi vedere dall'esempio sopra, ho scritto la funzione in modo tale che puoi specificare una o più colonne che dovrebbero essere trattate come colonne ID. Controlla se qualcuno dei file id.vars è duplicato e, in caso id.vars , genera una nuova variabile ID per te.

Puoi anche usare plyr per questo (usando i dati di esempio di @ AnadaMahto):

 > ddply(mydf, .(IDA), transform, .id = seq_along(IDA)) IDA IDB values .id 1 a 1 1 1 2 a 2 2 2 3 a 1 3 3 4 b 1 4 1 5 b 2 5 2 6 b 2 6 3 7 b 2 7 4 

o anche:

 > ddply(mydf, .(IDA, IDB), transform, .id = seq_along(IDA)) IDA IDB values .id 1 a 1 1 1 2 a 1 3 2 3 a 2 2 1 4 b 1 4 1 5 b 2 5 1 6 b 2 6 2 7 b 2 7 3 

Si noti che plyr non ha la reputazione di essere la soluzione più veloce, per questo è necessario dare un’occhiata a data.table .


Ecco un approccio data.table :

 library(data.table) DT <- data.table(mydf) DT[, .id := sequence(.N), by = "IDA,IDB"] DT # IDA IDB values .id # 1: a 1 1 1 # 2: a 2 2 1 # 3: a 1 3 2 # 4: b 1 4 1 # 5: b 2 5 1 # 6: b 2 6 2 # 7: b 2 7 3 

nel frattempo, puoi anche usare dplyr . se il tuo data.frame è chiamato mydata

 library(dplyr) mydata %>% group_by(CustomerID) %>% mutate(TripCounter = row_number()) 

Ho bisogno di farlo spesso e ho scritto una funzione che la realizza in modo diverso rispetto alle risposte precedenti. Non sono sicuro quale sia la soluzione più efficiente.

 idCounter <- function(x) { unlist(lapply(rle(x)$lengths, seq_len)) } mydf$TripCounter <- idCounter(mydf$CustomerID) 

Ecco il codice in codice della procedura. Non credo in cose come se stai usando loop in R, probabilmente stai facendo qualcosa di sbagliato

 x <- dataframe$CustomerID dataframe$counter <- 0 y <- dataframe$counter count <- 1 for (i in 1:length(x)) { ifelse (x[i] == x[i-1], count <- count + 1, count <- 1 ) y[i] <- count } dataframe$counter <- y 

Questa non è la risposta giusta ma mostra alcune cose interessanti rispetto ai cicli for, la vettorizzazione è veloce non interessa l’aggiornamento sequenziale. a <-read.table (textConnection ("CustomerID TripDate 1 1/3/2013 1 1/4/2013 1 1/9/2013 2 2/1/2013 2 2/4/2013 3 1/2/2013") , header = TRUE)

 a <- a %>% group_by(CustomerID,TripDate) # must in order res <- rep(1, nrow(a)) #base @ 1 res[2:6] <-sapply(2:6, function(i)if(a$CustomerID[i]== a$CustomerID[i - 1]) {res[i] = res[i-1]+1} else {res[i]= res[i]}) a$TripeCounter <- res