Jak zsumować zmienną według grupy?
Powiedzmy, że mam dwie kolumny danych. Pierwszy zawiera kategorie takie jak "pierwszy"," drugi"," trzeci " itp. Drugi ma liczby, które reprezentują liczbę razy widziałem "pierwszy".
Na przykład:
Category Frequency
First 10
First 15
First 5
Second 2
Third 14
Third 20
Second 3
Chcę posortować dane według kategorii i zsumować częstotliwości:
Category Frequency
First 30
Second 5
Third 34
Jak mam to zrobić w R?
10 answers
Używając aggregate
:
aggregate(x$Frequency, by=list(Category=x$Category), FUN=sum)
Category x
1 First 30
2 Second 5
3 Third 34
(embedding @thelatemail comment), aggregate
ma też interfejs formuły
aggregate(Frequency ~ Category, x, sum)
Lub jeśli chcesz połączyć wiele kolumn, możesz użyć notacji .
(działa również dla jednej kolumny)
aggregate(. ~ Category, x, sum)
Lub tapply
:
tapply(x$Frequency, x$Category, FUN=sum)
First Second Third
30 5 34
Wykorzystanie tych danych:
x <- data.frame(Category=factor(c("First", "First", "First", "Second",
"Third", "Third", "Second")),
Frequency=c(10,15,5,2,14,20,3))
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-03 23:06:55
Od niedawna możesz również użyć do tego celu pakietu dplyr:
library(dplyr)
x %>%
group_by(Category) %>%
summarise(Frequency = sum(Frequency))
#Source: local data frame [3 x 2]
#
# Category Frequency
#1 First 30
#2 Second 5
#3 Third 34
Lub dla wielu kolumn podsumowania (działa również z jedną kolumną):
x %>%
group_by(Category) %>%
summarise_each(funs(sum))
Aktualizacja dla dplyr >= 0.5: summarise_each
został zastąpiony przez summarise_all
, summarise_at
i summarise_if
rodzina funkcji w dplyr.
Lub, jeśli masz wiele kolumn do pogrupowania według, możesz określić wszystkie z nich w group_by
oddzielonych przecinkami:
mtcars %>%
group_by(cyl, gear) %>% # multiple group columns
summarise(max_hp = max(hp), mean_mpg = mean(mpg)) # multiple summary columns
Aby uzyskać więcej informacji, łącznie z operatorem %>%
, Zobacz wprowadzenie do dplyr .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-02 15:32:13
Odpowiedź udzielona przez rcs działa i jest prosta. Jeśli jednak obsługujesz większe zbiory danych i potrzebujesz zwiększenia wydajności, istnieje szybsza alternatywa: {]}
library(data.table)
data = data.table(Category=c("First","First","First","Second","Third", "Third", "Second"),
Frequency=c(10,15,5,2,14,20,3))
data[, sum(Frequency), by = Category]
# Category V1
# 1: First 30
# 2: Second 5
# 3: Third 34
system.time(data[, sum(Frequency), by = Category] )
# user system elapsed
# 0.008 0.001 0.009
Porównajmy to do tego samego, używając danych.ramka i wyżej:
data = data.frame(Category=c("First","First","First","Second","Third", "Third", "Second"),
Frequency=c(10,15,5,2,14,20,3))
system.time(aggregate(data$Frequency, by=list(Category=data$Category), FUN=sum))
# user system elapsed
# 0.008 0.000 0.015
I jeśli chcesz zachować kolumnę to jest składnia:
data[,list(Frequency=sum(Frequency)),by=Category]
# Category Frequency
# 1: First 30
# 2: Second 5
# 3: Third 34
Różnica będzie bardziej zauważalna przy większych zestawach danych, jak pokazuje poniższy kod:
data = data.table(Category=rep(c("First", "Second", "Third"), 100000),
Frequency=rnorm(100000))
system.time( data[,sum(Frequency),by=Category] )
# user system elapsed
# 0.055 0.004 0.059
data = data.frame(Category=rep(c("First", "Second", "Third"), 100000),
Frequency=rnorm(100000))
system.time( aggregate(data$Frequency, by=list(Category=data$Category), FUN=sum) )
# user system elapsed
# 0.287 0.010 0.296
Dla wielu agregacji, ty można łączyć lapply
i .SD
w następujący sposób
data[, lapply(.SD, sum), by = Category]
# Category Frequency
# 1: First 30
# 2: Second 5
# 3: Third 34
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-09 12:24:08
Jest to nieco związane z tym pytaniem .
Możesz również użyć funkcji by () :
x2 <- by(x$Frequency, x$Category, sum)
do.call(rbind,as.list(x2))
Te inne pakiety (plyr, reshape) mają tę zaletę, że zwracają dane.frame, ale warto się z nią zapoznać by (), ponieważ jest to funkcja bazowa.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:44
library(plyr)
ddply(tbl, .(Category), summarise, sum = sum(Frequency))
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-02 09:44:34
Kilka lat później, aby dodać kolejne proste rozwiązanie base R, którego nie ma tutaj z jakiegoś powodu - xtabs
xtabs(Frequency ~ Category, df)
# Category
# First Second Third
# 30 5 34
Or if want a data.frame
back
as.data.frame(xtabs(Frequency ~ Category, df))
# Category Freq
# 1 First 30
# 2 Second 5
# 3 Third 34
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-10 13:36:01
Aby dodać trzecią opcję:
require(doBy)
summaryBy(Frequency~Category, data=yourdataframe, FUN=sum)
EDIT: to bardzo stara odpowiedź. Teraz polecam użycie group_by i streszczenia z dplyr, jak w odpowiedzi @docendo.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-24 15:24:20
Podczas gdy ostatnio stałem się konwerterem na dplyr
dla większości tego typu operacji, pakiet sqldf
jest nadal naprawdę ładny (i IMHO bardziej czytelny) dla niektórych rzeczy.
Oto przykład jak na to pytanie można odpowiedzieć za pomocą sqldf
x <- data.frame(Category=factor(c("First", "First", "First", "Second",
"Third", "Third", "Second")),
Frequency=c(10,15,5,2,14,20,3))
sqldf("select
Category
,sum(Frequency) as Frequency
from x
group by
Category")
## Category Frequency
## 1 First 30
## 2 Second 5
## 3 Third 34
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-17 12:12:56
Jeśli x
jest ramką danych z Twoimi danymi, to następujące dane zrobią to, co chcesz:
require(reshape)
recast(x, Category ~ ., fun.aggregate=sum)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-02 09:44:03
Użycie cast
zamiast recast
(Uwaga 'Frequency'
jest teraz 'value'
)
df <- data.frame(Category = c("First","First","First","Second","Third","Third","Second")
, value = c(10,15,5,2,14,20,3))
install.packages("reshape")
result<-cast(df, Category ~ . ,fun.aggregate=sum)
Aby uzyskać:
Category (all)
First 30
Second 5
Third 34
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-25 15:43:56