2013-06-13 4 views
6

Ho alcuni dati:Aggiungere una colonna di ranghi

test <- data.frame(A=c("aaabbb", 
"aaaabb", 
"aaaabb", 
"aaaaab", 
"bbbaaa") 
) 

e così via. Tutti gli elementi hanno la stessa lunghezza e sono già ordinati prima che li ottenga.

Ho bisogno di creare una nuova colonna di ranghi, "Primo", "Secondo", "Terzo", qualsiasi cosa dopo di ciò può essere lasciata vuota, e ha bisogno di tenere conto dei legami. Quindi, nel caso di cui sopra, mi piacerebbe ottenere il seguente risultato:

A  B 
aaabbb First 
aaaabb Second 
aaaabb Second 
aaaaab Third 
bbbaaa 
bbbbaa 

Ho guardato rango() e alcuni altri posti che hanno usato, ma non ero in grado di arrivare a fare quello che ho stavo cercando.

risposta

3

ne dite di questo:

test$B <- match(test$A , unique(test$A)[1:3]) 
test 
     A B 
1 aaabbb 1 
2 aaaabb 2 
3 aaaabb 2 
4 aaaaab 3 
5 bbbaaa NA 
6 bbbbaa NA 

Uno dei tanti modi per fare questo. Forse non è il migliore, ma che mi viene subito in mente ed è abbastanza intuitivo. È possibile utilizzare unique perché si ricevono i dati pre-ordinati.

Quando i dati vengono ordinati un'altra funzione adatta da prendere in considerazione è rle, anche se è leggermente più ottuso in questo esempio:

rnk <- rle(as.integer(df$A))$lengths 
rnk 
# [1] 1 2 1 1 1 
test$B <- c(rep(1:3 , times = rnk[1:3]) , rep(NA, sum(rnk[-c(1:3)]))) 

rle calcola le lunghezze (e dei valori che non si preoccupano veramente qui) di esecuzioni di valori uguali in un vettore, quindi di nuovo funziona perché i dati sono già ordinati.

E se non lo fai avere avere spazi vuoti dopo il terzo elemento classificato è ancora più semplice (e più leggibile):

test$B <- rep(1:length(rnk),times=rnk) 
+0

Non so, penso che sia dannatamente bello. – thelatemail

+0

@thelatemail lol, evviva. Credo di si. Stavo anche pensando a 'rle' dato che i dati sono ordinati. Sembra appropriato quindi lo aggiungerò come alternativa. –

+0

Questo è esattamente quello che stavo cercando. Grazie! – pak

3

Questa sembra una buona domanda di fattori:

test$B <- as.numeric(factor(test$A, levels = unique(test$A))) 

cumsum viene anche in mente, dove aggiungiamo 1 ogni volta che il valore cambia:

test$B <- cumsum(c(TRUE, tail(test$A, -1) != head(test$A, -1))) 

(Come @Simon ha detto, ci sono molti modi per farlo ...)

+0

+1 per il metodo di offset di testa e croce. Intelligente. –

+1

Anche questo è utile, specialmente se tutto deve essere classificato. In questo caso particolare, erano solo i primi 3. Grazie. A volte penso che sia fantastico che ci siano così tanti modi di fare le cose, ea volte mi viene voglia di accendere i miei capelli. – pak

+0

@flodel. Ho appena testato la tua prima risposta (usando i fattori) su alcuni dei miei dati e ho capito che non funziona correttamente in tutti i casi. Questo perché è possibile dire, testare $ A [10] in ** look ** come se fosse uguale a test $ A [6], con gli elementi intermedi diversi. Trattarli come fattori costringe l'uguaglianza dove potrebbe non esserlo, in questo caso. – pak