R 计算每组的行数,并将结果添加到原始数据帧

R 计算每组的行数,并将结果添加到原始数据帧,r,count,aggregate,r-faq,R,Count,Aggregate,R Faq,假设我有一个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)) 或者也可以使用plyr,(尽管我不确定如何使用) 但是,如何将结果合并到原始数据框中?结果如下所示: df # name

假设我有一个
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))
或者也可以使用
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
# 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")]))
其中
count
现在存储聚合结果

使用
plyr
的解决方案也很有意思,不过我想看看如何使用base R实现这一点。

您可以这样做:

> 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

您可以使用
ave

df$count <- ave(df$num, df[,c("name","type")], FUN=length)

df$count使用
数据。表

library(data.table)
dt = as.data.table(df)

# or coerce to data.table by reference:
# setDT(df)

dt[ , count := .N, by = .(name, type)]
library(dplyr)
df %>%
  group_by(name, type) %>%
  mutate(count = n())
plyr::ddply(df, .(name, type), transform, count = length(num))
有关预处理的
数据。表1.8.2
备选方案,请参阅编辑历史记录


使用
dplyr

library(data.table)
dt = as.data.table(df)

# or coerce to data.table by reference:
# setDT(df)

dt[ , count := .N, by = .(name, type)]
library(dplyr)
df %>%
  group_by(name, type) %>%
  mutate(count = n())
plyr::ddply(df, .(name, type), transform, count = length(num))
或者简单地说:

add_count(df, name, type)

使用
plyr

library(data.table)
dt = as.data.table(df)

# or coerce to data.table by reference:
# setDT(df)

dt[ , count := .N, by = .(name, type)]
library(dplyr)
df %>%
  group_by(name, type) %>%
  mutate(count = n())
plyr::ddply(df, .(name, type), transform, count = length(num))

另一种概括更多的方式:

df$count <- unsplit(lapply(split(df, df[c("name","type")]), nrow), df[c("name","type")])

df$count基本
R
函数
aggregate
将使用一行代码获取计数,但将这些计数添加回原始
数据。帧
似乎需要一些处理

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

df这应该可以完成您的工作:

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_agg一个两行的替代方法是生成一个0的变量,然后用
split将行数合并到基本数据集中只差一步

使用
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
df使用sqldf包:


以R为底的一条简单线:

df$count = table(interaction(df[, (c("name", "type"))]))[interaction(df[, (c("name", "type"))])]
为清晰/高效起见,两行相同:

fact = interaction(df[, (c("name", "type"))])
df$count = table(fact)[fact]

请解释这是如何更一般化的?您是否需要“setkeyv(dt,c('name','type')”?也可以使用
transform(df,count=ave(num,name,type,FUN=length))
with