2012-04-16 15 views
27

Mam ramkę danych, w której jedna kolumna to nazwy gatunków, a druga kolumna to wartości liczebności. Ze względu na procedurę pobierania próbek niektóre gatunki pojawiają się więcej niż jeden raz (tj. Występuje więcej niż jeden rząd z gatunkiem X). Chciałbym skonsolidować te wpisy i zsumować ich obfitość.Skonsoliduj duplikaty wierszy

Na przykład, biorąc pod uwagę to ramka danych:

set.seed(6) 
df=data.frame(
    x=c("sp1","sp2","sp3","sp3","sp4","sp2","sp3"), 
    y=rpois(7,2)); df 

która produkuje:

x y 
1 sp1 2 
2 sp2 4 
3 sp3 1 
4 sp3 1 
5 sp4 3 
6 sp2 5 
7 sp3 5 

Chciałbym zamiast produkować:

x y 
1 sp1 2  
2 sp2 9  (5+4) 
3 sp3 7  (5+1+1) 
5 sp4 3 

Z góry dziękuję za wszelką pomoc ty może dostarczyć!

Odpowiedz

35

Działa:

library(plyr) 
ddply(df,"x",numcolwise(sum)) 

słowami: (1) podzielony na ramki danych df w kolumnie "x"; (2) dla każdej porcji, weź sumę każdej kolumny o wartości liczbowej; (3) przyklejają wyniki z powrotem do pojedynczej ramki danych. (dd w ddply oznacza "ma d ata ramki jako wejście zwrócić d ata ramce")

Innym ewentualnie jaśniejsze podejście:

aggregate(y~x,data=df,FUN=sum) 

Patrz quick/elegant way to construct mean/variance summary table pokrewnego (nieco bardziej złożone) pytanie.

+0

D'oh! Jak ta podręcznikowa aplikacja ddply przemknęła obok mnie ... Dzięki Ben! – jslefche

+0

+1 dla zastosowania liczby mnogiej i sumy. Miałem kłopoty z transformacją i mutacją, starając się, aby to wszystko działało. –

+1

AFAIK, "agregacja (y ~ x + z, dane = df, FUN = suma)" może być użyta do zachowania * dodatkowej * kolumny (tutaj "z"), jeśli zajdzie taka potrzeba (czy była potrzeba w moim przypadku).Proszę popraw mnie jeżeli się mylę. – Shadow

20

Proste jak aggregate:

aggregate(df['y'], by=df['x'], sum) 
6
> tapply(df$y, df$x, sum) 
sp1 sp2 sp3 sp4 
    2 9 7 3 

jeśli ma być odebrać data.frame Bena działa świetnie. lub możesz przymusić wyjście tapply.

out <- tapply(df$y, df$x, sum) 
>  data.frame(x=names(out), y=out, row.names=NULL) 
    x y 
1 sp1 2 
2 sp2 9 
3 sp3 7 
4 sp4 3 
8

data.table rozwiązanie dla czasu i wydajności pamięci

library(data.table) 
DT <- as.data.table(df) 
# which columns are numeric 
numeric_cols <- which(sapply(DT, is.numeric)) 
DT[, lapply(.SD, sum), by = x, .SDcols = numeric_cols] 

Lub, w danym przypadku, biorąc pod uwagę, że wiesz, że tam jest tylko kolumna y 1 chcesz podsumować ponad

DT[, list(y=sum(y)),by=x] 
1

MWE, aby sprawdzić, czy wzór do przestrzegania drugiej zmiennej (tj. Tutaj "Z" i oprócz "X", faktycznie działałby:

example = data.frame(X=c("x"),Z=c("a"),Y=c(1), stringsAsFactors=F) 
newrow = c("y","b",1) 
example <- rbind(example, newrow) 
newrow = c("z","a",0.5) 
example <- rbind(example, newrow) 
newrow = c("x","b",1) 
example <- rbind(example, newrow) 
newrow = c("x","b",2) 
example <- rbind(example, newrow) 
newrow = c("y","b",10) 
example <- rbind(example, newrow) 
example$X = as.factor(example$X) 
example$Z = as.factor(example$Z) 
example$Y = as.numeric(example$Y) 
example_agg <- aggregate(Y~X+Z,data=example,FUN=sum) 
6

dplyr rozwiązanie:

library(dplyr) 
df %>% group_by(x) %>% summarise(y = sum(y))