Come aggiungere il conteggio dei valori univoci per gruppo a R data.frame

Desidero contare il numero di valori univoci raggruppando una seconda variabile e quindi aggiungere il conteggio al data.frame esistente come nuova colonna. Ad esempio, se il frame di dati esistente è simile a questo:

color type 1 black chair 2 black chair 3 black sofa 4 green sofa 5 green sofa 6 red sofa 7 red plate 8 blue sofa 9 blue plate 10 blue chair 

Voglio aggiungere per ogni color , il numero di types unici presenti nei dati:

  color type unique_types 1 black chair 2 2 black chair 2 3 black sofa 2 4 green sofa 1 5 green sofa 1 6 red sofa 2 7 red plate 2 8 blue sofa 3 9 blue plate 3 10 blue chair 3 

Speravo di usare ave , ma non riesco a trovare un metodo semplice che non richieda molte linee. Ho> 100.000 righe, quindi non sono sicuro di quanto sia importante l’efficienza.

È in qualche modo simile a questo problema: conta il numero di osservazioni / righe per gruppo e aggiunge il risultato al frame di dati

Usando ave (dato che lo chiedi specificamente):

 within(df, { count <- ave(type, color, FUN=function(x) length(unique(x)))}) 

Assicurati che quel type sia carattere vettoriale e non fattore.


Dato che anche i tuoi dati sono enormi e che la velocità / le prestazioni potrebbero essere un fattore, suggerirei anche una soluzione data.table .

 require(data.table) setDT(df)[, count := uniqueN(type), by = color] # v1.9.6+ # if you don't want df to be modified by reference ans = as.data.table(df)[, count := uniqueN(type), by = color] 

uniqueN stato implementato in v1.9.6 ed è un equivalente più veloce della length(unique(.)) . Inoltre funziona anche con data.frames / data.tables.


Altre soluzioni:

Utilizzando plyr:

 require(plyr) ddply(df, .(color), mutate, count = length(unique(type))) 

Utilizzo di aggregate :

 agg <- aggregate(data=df, type ~ color, function(x) length(unique(x))) merge(df, agg, by="color", all=TRUE) 

Ecco una soluzione con il pacchetto dplyr – ha n_distinct() come wrapper per length(unique()) .

 df %>% group_by(color) %>% mutate(unique_types = n_distinct(type)) 

Questo può anche essere ottenuto in un vettore senza operazioni di gruppo combinando unique con table o tabulate

Se df$color è un factor , allora

O

 table(unique(df)$color)[as.character(df$color)] # black black black green green red red blue blue blue # 2 2 2 1 1 2 2 3 3 3 

O

 tabulate(unique(df)$color)[as.integer(df$color)] # [1] 2 2 2 1 1 2 2 3 3 3 

Se df$color è character allora basta

 table(unique(df)$color)[df$color] 

Se df$color è un integer allora solo

 tabulate(unique(df)$color)[df$color]