たとえば、data.frame
オブジェクト:
df <- data.frame(name=c('black','black','black','red','red'),
type=c('chair','chair','sofa','sofa','plate'),
num=c(4,5,12,4,3))
次に、name
とtype
の各組み合わせの観測数をカウントします。これは次のように実行できます。
table(df[ , c("name","type")])
または場合によってはplyr
も使用します(ただし、方法はわかりません)。
ただし、元のデータフレームに結果を組み込むにはどうすればよいですか?結果は次のようになります。
df
# name type num count
# 1 black chair 4 2
# 2 black chair 5 2
# 3 black sofa 12 1
# 4 red sofa 4 1
# 5 red plate 3 1
ここで、count
には、集計の結果が格納されます。
plyr
を使用したソリューションも興味深いものになりますが、これがベースRでどのように行われるかを知りたいと思います。
plyr
:を使用
plyr::ddply(df, .(name, type), transform, count = length(num))
data.table
:を使用
library(data.table)
dt = data.table(df)
# using setkey or setkeyv to set the key
setkeyv(dt, c('name', 'type'))
# self
dt[dt[ , count = length(num), 'name, type']]
編集(mnel)
data.table
バージョン1.8.2以降を使用すると、グループごとに:=
が使用されます。値.N
(バージョン1.6.2を導入)もあります。これはグループ内の行数です)、次のように簡単です。
dt[ , count := .N, by = list(name, type)]
dplyr
:を使用
library(dplyr)
df %>%
group_by(name, type) %>%
mutate(count = n())
または単に:
add_count(df, name, type)
ave
を使用できます:
df$count <- ave(df$num, df[,c("name","type")], FUN=length)
あなたはこれを行うことができます:
> ddply(df,.(name,type),transform,count = NROW(piece))
name type num count
1 black chair 4 2
2 black chair 5 2
3 black sofa 12 1
4 red plate 3 1
5 red sofa 4 1
またはおそらくより直感的に、
> ddply(df,.(name,type),transform,count = length(num))
name type num count
1 black chair 4 2
2 black chair 5 2
3 black sofa 12 1
4 red plate 3 1
5 red sofa 4 1
これはあなたの仕事をするはずです:
df_agg <- aggregate(num~name+type,df,FUN=NROW)
names(df_agg)[3] <- "count"
df <- merge(df,df_agg,by=c('name','type'),all.x=TRUE)
ベースR
関数aggregate
は、1行でカウントを取得しますが、それらのカウントを元のdata.frame
は少し処理がかかるようです。
df <- data.frame(name=c('black','black','black','red','red'),
type=c('chair','chair','sofa','sofa','plate'),
num=c(4,5,12,4,3))
df
# name type num
# 1 black chair 4
# 2 black chair 5
# 3 black sofa 12
# 4 red sofa 4
# 5 red plate 3
rows.per.group <- aggregate(rep(1, length(paste0(df$name, df$type))),
by=list(df$name, df$type), sum)
rows.per.group
# Group.1 Group.2 x
# 1 black chair 2
# 2 red plate 1
# 3 black sofa 1
# 4 red sofa 1
my.summary <- do.call(data.frame, rows.per.group)
colnames(my.summary) <- c(colnames(df)[1:2], 'rows.per.group')
my.data <- merge(df, my.summary, by = c(colnames(df)[1:2]))
my.data
# name type num rows.per.group
# 1 black chair 4 2
# 2 black chair 5 2
# 3 black sofa 12 1
# 4 red plate 3 1
# 5 red sofa 4 1
sqldfパッケージを使用:
library(sqldf)
sqldf("select a.*, b.cnt
from df a,
(select name, type, count(1) as cnt
from df
group by name, type) b
where a.name = b.name and
a.type = b.type")
# name type num cnt
# 1 black chair 4 2
# 2 black chair 5 2
# 3 black sofa 12 1
# 4 red sofa 4 1
# 5 red plate 3 1
行カウントを基本データセットに組み込むには、わずか1ステップでした。
broom
パッケージのtidy()
関数を使用して、頻度テーブルをデータフレームに変換し、df
との内部結合を作成します。
df <- data.frame(name=c('black','black','black','red','red'),
type=c('chair','chair','sofa','sofa','plate'),
num=c(4,5,12,4,3))
library(broom)
df <- merge(df, tidy(table(df[ , c("name","type")])), by=c("name","type"))
df
name type num Freq
1 black chair 4 2
2 black chair 5 2
3 black sofa 12 1
4 red plate 3 1
5 red sofa 4 1
2行の代替方法は、0の変数を生成し、次のように_split<-
_、split
、およびlengths
で埋めることです。
_# generate vector of 0s
df$count <-0L
# fill it in
split(df$count, df[c("name", "type")]) <- lengths(split(df$num, df[c("name", "type")]))
_
これは望ましい結果を返します
_df
name type num count
1 black chair 4 2
2 black chair 5 2
3 black sofa 12 1
4 red sofa 4 1
5 red plate 3 1
_
基本的に、RHSは各名前とタイプの組み合わせの長さを計算し、「red.chair」と「black.plate」に対して0の長さ6の名前付きベクトルを返します。これは_split <-
_でLHSに供給されます。これはベクトルを取得し、指定されたスポットに適切に値を追加します。 ave
の2行目から最終行までがわかるように、これは基本的にave
が行うことです。
_split(x, g) <- lapply(split(x, g), FUN)
_
ただし、lengths
はsapply(list, length)
の最適化バージョンです。