统计每个组的观察值/行数,并将结果添加到数据帧
说我有一个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
的解决方案也很有趣,但是我想知道如何用base 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())
随着新版本的dplyr
( 0.6.0
)
df %>% add_count(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)
另一种推广更多的方式:
df$count <- unsplit(lapply(split(df, df[c("name","type")]), nrow), df[c("name","type")])
基本的R
函数aggregate
将获得data.frame
计数,但将这些计数加回到原始数据。 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
一个两行的替代方法是生成一个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”返回长度为6的命名向量为0。 这被送到LHS与split <-
这将采取向量,并适当地增加值在他们的给定点。 这实际上就是ave
所做的,正如你所看到的, ave
的第二个到最后一行是
split(x, g) <- lapply(split(x, g), FUN)
然而, lengths
是sapply(list, length)
的优化版本。