2列のデータがあるとしましょう。 1つ目は、 "First"、 "Second"、 "Third"などのカテゴリを含みます。
例えば:
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でどうやってやるのでしょうか。
aggregate
を使う:
aggregate(x$Frequency, by=list(Category=x$Category), FUN=sum)
Category x
1 First 30
2 Second 5
3 Third 34
上記の例では、list
に複数の次元を指定できます。同じデータ型の複数の集約メトリックをcbind
経由で組み込むことができます。
aggregate(cbind(x$Frequency, x$Metric2, x$Metric3) ...
(@thelatemailコメントを埋め込む)、aggregate
は式のインターフェースも持っています
aggregate(Frequency ~ Category, x, sum)
あるいは、複数の列を集約したい場合は、.
表記を使用することができます(1つの列に対しても機能します)。
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))
最近では、そのために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
または、複数の集計列の場合(1列でも機能します)。
x %>%
group_by(Category) %>%
summarise_each(funs(sum))
dplyr> = 0.5に更新:summarise_each
は、dplyrのsummarise_all
、summarise_at
およびsummarise_if
関数ファミリーに置き換えられました。
または、でグループ化する複数の列がある場合は、カンマで区切ってgroup_by
にそれらすべてを指定できます。
mtcars %>%
group_by(cyl, gear) %>% # multiple group columns
summarise(max_hp = max(hp), mean_mpg = mean(mpg)) # multiple summary columns
%>%
演算子を含む詳細については、dplyrの の紹介 を参照してください。
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.frameと上記のものを使って同じものと比較しましょう。
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
これは、この質問に多少 関連しています 。
あなたはまたちょうど使用することができます によって() 関数:
x2 <- by(x$Frequency, x$Category, sum)
do.call(rbind,as.list(x2))
これらの他のパッケージ(plyr、reshape)にはdata.frameを返すという利点がありますが、by()は基本関数なので、よく知っておく価値があります。
library(plyr)
ddply(tbl, .(Category), summarise, sum = sum(Frequency))
数年後、何らかの理由でここには存在しない別の単純なbase Rソリューションを追加するためにxtabs
xtabs(Frequency ~ Category, df)
# Category
# First Second Third
# 30 5 34
あるいはdata.frame
を返したい場合
as.data.frame(xtabs(Frequency ~ Category, df))
# Category Freq
# 1 First 30
# 2 Second 5
# 3 Third 34
3番目のオプションを追加するだけです:
require(doBy)
summaryBy(Frequency~Category, data=yourdataframe, FUN=sum)
編集:これは非常に古い答えです。 @docendo answerのように、summarise
からgroup_by
とdplyr
を使用することをお勧めします。
x
があなたのデータを含むデータフレームであるならば、以下はあなたが望むことをするでしょう:
require(reshape)
recast(x, Category ~ ., fun.aggregate=sum)
私は最近これらのタイプの操作の大部分で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
私は ave
が異なる列に異なる集計関数を適用する必要があるときに(そしてベースRに固執したいときに)非常に役立つ(そして効率的)と思います:
例えば.
この入力を考えると:
DF <-
data.frame(Categ1=factor(c('A','A','B','B','A','B','A')),
Categ2=factor(c('X','Y','X','X','X','Y','Y')),
Samples=c(1,2,4,3,5,6,7),
Freq=c(10,30,45,55,80,65,50))
> DF
Categ1 Categ2 Samples Freq
1 A X 1 10
2 A Y 2 30
3 B X 4 45
4 B X 3 55
5 A X 5 80
6 B Y 6 65
7 A Y 7 50
Categ1
とCateg2
でグループ化し、Samples
の合計とFreq
の平均を計算します。
これはave
を使った可能な解決策です:
# create a copy of DF (only the grouping columns)
DF2 <- DF[,c('Categ1','Categ2')]
# add sum of Samples by Categ1,Categ2 to DF2
# (ave repeats the sum of the group for each row in the same group)
DF2$GroupTotSamples <- ave(DF$Samples,DF2,FUN=sum)
# add mean of Freq by Categ1,Categ2 to DF2
# (ave repeats the mean of the group for each row in the same group)
DF2$GroupAvgFreq <- ave(DF$Freq,DF2,FUN=mean)
# remove the duplicates (keep only one row for each group)
DF2 <- DF2[!duplicated(DF2),]
結果:
> DF2
Categ1 Categ2 GroupTotSamples GroupAvgFreq
1 A X 6 45
2 A Y 9 40
3 B X 7 50
6 B Y 6 65
最近追加されたdplyr::tally()
は今これをこれまで以上に簡単にします:
tally(x, Category)
Category n
First 30
Second 5
Third 34
packageRfastの関数group.sum
を使うことができます。
Category <- Rfast::as_integer(Category,result.sort=FALSE) # convert character to numeric. R's as.numeric produce NAs.
result <- Rfast::group.sum(Frequency,Category)
names(result) <- Rfast::Sort(unique(Category)
# 30 5 34
Rfastには多くのグループ関数があり、そのうちの1つがgroup.sum
です。
cast
の代わりにrecast
を使用する('Frequency'
は'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)
取得するため:
Category (all)
First 30
Second 5
Third 34