2009-11-02 71 views
207

假設我有兩列數據。第一個包含「First」,「Second」,「Third」等類別。第二個包含的數字表示我看到「First」的次數。如何按組分組變量?

例如:

Category  Frequency 
First  10 
First  15 
First  5 
Second  2 
Third  14 
Third  20 
Second  3 

我想按類別對數據進行排序,總結頻率:

Category  Frequency 
First  30 
Second  5 
Third  34 

我將如何做到這一點的R'

回答

234

使用aggregate

aggregate(x$Frequency, by=list(Category=x$Category), FUN=sum) 
    Category x 
1 First 30 
2 Second 5 
3 Third 34 

(嵌入@thelatemail評論),aggregate有一個公式界面太

aggregate(Frequency ~ Category, x, sum) 

或者,如果你想要聚合多列,您可以使用.表示法(適用於一列)

aggregate(. ~ Category, x, sum) 

tapply

tapply(x$Frequency, x$Category, FUN=sum) 
First Second Third 
    30  5  34 

使用該數據:

x <- data.frame(Category=factor(c("First", "First", "First", "Second", 
             "Third", "Third", "Second")), 
        Frequency=c(10,15,5,2,14,20,3)) 
+2

@AndrewMcKinlay,R使用代字號來定義符號公式,用於統計和其他功能。它可以解釋爲*「按類別分類的頻率」*或*「頻率取決於類別」*。並非所有的語言都使用特殊的運算符來定義符號函數,如R所示。也許用波浪算子的「自然語言解釋」,它變得更有意義(甚至直覺)。我個人發現這個符號公式表示比一些更冗長的選擇更好。 – r2evans 2016-12-19 04:35:12

13

如果x與您的數據的數據幀,那麼下面會做你想要什麼:

require(reshape) 
recast(x, Category ~ ., fun.aggregate=sum) 
19
library(plyr) 
ddply(tbl, .(Category), summarise, sum = sum(Frequency)) 
15

只是爲了增加了第三種選擇:

require(doBy) 
summaryBy(Frequency~Category, data=yourdataframe, FUN=sum) 

編輯:這是一個非常古老的答案。現在我會推薦使用group_by並從dplyr中進行彙總,就像在@docendo中一樣。

30

這有點related to this question

您也可以只使用由()功能:

x2 <- by(x$Frequency, x$Category, sum) 
do.call(rbind,as.list(x2)) 

那些其他包(plyr,重塑)有返回data.frame的好處,但它是值得熟悉的( ),因爲它是一個基本功能。

48

由rcs提供的答案作品很簡單。不過,如果你正在處理更大的數據集,需要一個性能提升有一個更快的替代方案:

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 

我們來比較一下使用的數據是一樣的。框架和凌駕於:

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 

如果你想保持柱這是語法:

data[,list(Frequency=sum(Frequency)),by=Category] 
# Category Frequency 
# 1: First  30 
# 2: Second   5 
# 3: Third  34 

的差異將成爲大數據集更明顯,如下面的代碼演示:

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 

對於多個聚合,你可以結合lapply.SD如下

data[, lapply(.SD, sum), by = Category] 
# Category Frequency 
# 1: First  30 
# 2: Second   5 
# 3: Third  34 
+7

+1但是0.296 vs 0.059並不是特別令人印象深刻。數據大小需要遠遠大於300k行,並且有多於3個組,data.table才能發光。例如,我們將嘗試支持超過20億行,因爲一些data.table用戶擁有250GB的RAM,而GNU R現在支持長度> 2^31。 – 2013-09-09 10:05:06

+1

是的。事實證明,儘管我沒有所有的RAM,並且只是試圖提供一些data.table的卓越性能的證據。我相信隨着更多數據的差異會更大。 – asieira 2013-10-23 23:22:16

+0

我有7密耳觀察dplyr花了0.3秒,聚合()花費了22秒來完成操作。我打算在這個話題上發佈它,你擊敗了我! – zazu 2015-11-14 19:10:11

114

最近,您還可以使用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 

或者,多個摘要列(有一列工程太):

x %>% 
    group_by(Category) %>% 
    summarise_each(funs(sum)) 

更新爲dplyr> = 0.5:summarise_each已被summarise_allsummarise_atsummarise_if替換爲dplyr中的函數族。

或者,如果你有多列小組通過,您可以指定所有的人都在用逗號分隔的group_by

mtcars %>% 
    group_by(cyl, gear) %>%       # multiple group columns 
    summarise(max_hp = max(hp), mean_mpg = mean(mpg)) # multiple summary columns 

欲瞭解更多信息,包括%>%運營商,看到introduction to dplyr

+0

與其他答案中提供的data.table和aggregate方案相比,它有多快? – asieira 2015-01-23 14:35:58

+2

@asieira,這是最快的,差異有多大(或者差異是否明顯)將取決於您的數據大小。通常,對於大型數據集(例如某些GB),data.table最可能是最快的。在較小的數據大小上,data.table和dplyr通常很接近,也取決於組數。數據,表格和dplyr都比基本功能要快很多(但對某些操作來說,可能會快100-1000倍)。另見[這裏](http://stackoverflow.com/questions/21435339/data-table-vs-dplyr-can-one-do-something-well-the-other-cant-or-does-poorly) – 2015-01-23 14:50:59

15

若干年後,只需添加一個不存在這裏一些reason- xtabs

xtabs(Frequency ~ Category, df) 
# Category 
# First Second Third 
# 30  5  34 

另一種簡單的基礎R解決方案或者,如果想回data.frame

as.data.frame(xtabs(Frequency ~ Category, df)) 
# Category Freq 
# 1 First 30 
# 2 Second 5 
# 3 Third 34 
14

雖然我最近成爲轉換爲dplyr大多數這些類型的操作,sqldf包仍然是非常好的(和恕我直言更可讀)的一些事情。

下面是一個如何這個問題可以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 
0

使用cast代替recast與回答一個例子(注意現在'value''Frequency'是)

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) 

獲得:

Category (all) 
First  30 
Second 5 
Third  34