2013-07-02 6 views
33

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 esistenti si presenta così:Come aggiungere il conteggio dei valori univoci per gruppo a R data.frame

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 conteggio dei unico types che sono 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 utilizzare ave, ma non riesco a trovare un metodo semplice che non richiede molte linee. Ho> 100.000 righe, quindi non sono sicuro di quanto sia importante l'efficienza.

E 'in qualche modo simile a questo problema: Count number of observations/rows per group and add result to data frame

risposta

39

Utilizzando ave (dal momento che si chiede specificamente):

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

Assicurarsi che type è il vettore di carattere e non fattore.


Dal momento che dici anche i dati è enorme e che la velocità/prestazioni può quindi essere un fattore, io suggerirei una soluzione data.table pure.

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 attuato nel v1.9.6 ed è un veloce equivalente di length(unique(.)). Inoltre funziona anche con data.frames/data.tables.


Altre soluzioni:

Utilizzando plyr:

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

Uso aggregate:

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

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

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

Ciò può essere ottenuto anche in un vettorizzata senza per operazioni di gruppo combinando unique con table o tabulate

Se df$color è factor, quindi

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 

Or

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

Se df$color è character poi basta

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

Se df$color è un integer poi basta

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