2013-06-27 4 views
5

questo è il mio primo post e io sono nuovo di programmazione e R.Utilizzando R, Come faccio a contrassegnare i valori duplicati in sequenza in un'unica colonna di un dataframe

Sto cercando di creare una nuova colonna per contrassegnare o contrassegna i valori sequenzialmente duplicati in una colonna separata.

df < - c (2,2,2,2,3,4,3,4,3,4,2,3,7,7,7))

Utilizzando la funzione restituisce il duplicato seguente:

data.frame (value = df, bandiera = duplicato (df))

value flag 
1  2 FALSE 
2  2 TRUE 
3  2 TRUE 
4  2 TRUE 
5  3 FALSE 
6  4 FALSE 
7  3 TRUE 
8  4 TRUE 
9  3 TRUE 
10  4 TRUE 
11  2 TRUE 
12  3 TRUE 
13  7 FALSE 
14  7 TRUE 
15  7 TRUE 

Quello che mi piacerebbe è:

value flag 
1  2 TRUE 
2  2 TRUE 
3  2 TRUE 
4  2 TRUE 
5  3 FALSE 
6  4 FALSE 
7  3 FALSE 
8  4 FALSE 
9  3 FALSE 
10  4 FALSE 
11  2 FALSE 
12  3 FALSE 
13  7 TRUE  
14  7 TRUE  
15  7 TRUE  

Il mio set di dati ha ove r 2 milioni di osservazioni, quindi idealmente la soluzione sarebbe efficiente.

Grazie, John

+0

Dato che sei relativamente nuovo qui puoi leggere il [** circa **] (http://stackoverflow.com/about) e il [** faq **] (http: // stackoverflow.com/faq) su come funziona SO. StackOverflow è reso molto più prezioso per tutti se quando ricevi una risposta che risolve il tuo problema, lo accetti facendo clic sul piccolo segno di spunta o upvote una risposta utile. Non sei assolutamente obbligato a farlo, ma è un ottimo modo per "restituire" al sito se una risposta ha effettivamente risolto il tuo problema e aiuta a mantenere il sito libero da domande senza risposta a cui è stata data risposta. Grazie! –

risposta

7

rle si ottiene ciò che siete dopo in combinazione con rep

rl <- rle(df) 
rep(rl$lengths != 1 , times = rl$lengths) 
# [1] TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE TRUE 
# [15] TRUE 

e credo rle è abbastanza efficiente.

Timing (MBP fine del 2008) su un vettore di lunghezza 2E6:

system.time({ rl <- rle(df) 
res <- rep(rl$lengths != 1 , times = rl$lengths) 
}) 
# user system elapsed 
# 0.449 0.106 0.559 
+0

Hah! Avevo iniziato a pensare a questo problema con 'rle' e poi ho visto la tua risposta e cambiato. E ora sei passato a 'rle'. :) – asb

+0

Immagino tu abbia capito prima di me che l'approccio più vecchio non andava da nessuna parte. Upvote. – asb

+0

@asb lol, che spesso mi succede !! Grazie per l'upvote :-) –

2

Dal momento che si dispone di più di 2 milioni Consiglierei davvero di passare a data.table. Qui la mia soluzione utilizzando rle simile a @Simon uno, ho appena scritto la sua versione data.table. Credo che non sia sempre ovvio soprattutto per i principianti (come me sotto data.table).

library(data.table) 
set.seed(1234) 
dd <- sample(1:20, 2e+06, rep = TRUE) 
DT <- data.table(dd) 
system.time(DT[, `:=`(grp2, { 
          dd.rle = rle(dd) ## store rle to not call it twice 
          rep(dd.rle$lengths > 1, times = dd.rle$lengths) 
      })]) 
## user system elapsed 
## 1.17 0.06 1.28 
## user system elapsed <- rle twice 
## 1.69 0.11 1.86 

##  dd grp2 
## 1e+00: 3 FALSE 
## 2e+00: 13 TRUE 
## 3e+00: 13 TRUE 
## 4e+00: 13 TRUE 
## 5e+00: 18 FALSE 
## ---   
## 2e+06: 6 FALSE 
## 2e+06: 5 FALSE 
## 2e+06: 4 FALSE 
## 2e+06: 10 FALSE 
## 2e+06: 13 FALSE 
+0

+1 Stavo per farlo, onesto! Ho appena deciso che mi ci vorrà troppo tempo per capire - SUCCO ancora a 'data.table' Bel lavoro. –

+0

@ SimonO101 grazie. – agstudy

+2

Forse potresti essere ancora più veloce non usando 'rle' due volte? –

Problemi correlati