2013-07-02 11 views
33

Chcę policzyć liczbę unikatowych wartości, grupując drugą zmienną, a następnie dodać liczbę do istniejącego data.frame jako nowej kolumny. Na przykład, jeśli istniejąca ramka danych wygląda następująco:Jak dodać liczbę unikatowych wartości przez grupę do 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 

chcę dodać do każdego color, liczba unikalnych types które są obecne w danych:

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 

Ja ufałem użyj ave, ale nie można znaleźć prostej metody, która nie wymaga wielu wierszy. Mam> 100 000 wierszy, więc nie jestem też pewien, jak ważna jest wydajność.

Jest nieco podobny do tego problemu: Count number of observations/rows per group and add result to data frame

Odpowiedz

39

Korzystanie ave (skoro pytasz o to specjalnie):

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

Upewnij się, że type jest wektor znaków, a nie czynnikiem.


Ponieważ również powiedzieć, dane są ogromne, a prędkość/wydajność może zatem być czynnikiem, chciałbym zaproponować rozwiązanie data.table również.

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 zrealizowano w v1.9.6 i jest szybciej równoważnik length(unique(.)). Ponadto działa również z danymi.


Inne rozwiązania:

Korzystanie plyr:

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

Korzystanie aggregate:

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

Oto rozwiązanie z pakietem dplyr - ma n_distinct() jako otoczka do length(unique()) .

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

Można to również osiągnąć w zwektoryzowany bez operacjami grupy łącząc unique z table lub tabulate

If df$color jest factor, następnie

albo

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 

lub

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

Jeśli df$color jest character wtedy właśnie

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

Jeśli df$color jest integer wtedy właśnie

tabulate(unique(df)$color)[df$color] 
Powiązane problemy