2016-01-21 70 views
1

我有一个数据帧DF,3个变量:ID,类别和数量:合并和汇总结果的原始数据

id category quantity 
01 AB  235 
02 BC  987 
03 AB  366 
04 CD  287 

我想添加一个第四个变量是全品类的总和。现在,我是这样做的:

df <- merge(df,aggregate(df$quantity,list(df$category),sum), 
    by.x="category", 
    by.y="Group.1") 
names(df)[4] <- "sum.category" 

它的工作原理,但我不觉得很满意,有可能是一个更好的办法?

+0

@帕斯卡尔:做完了,抱歉给您带来不便 – Malta

回答

3

这是data.table的另一种选择。我们将'data.frame'转换为'data.table'(setDT(df1)),按'category'分组,我们将'quantity'的sum作为新列('sum.category')分配(:=)。

library(data.table) 
setDT(df1)[,sum.category:= sum(quantity) , category] 
df1 
# id category quantity sum.category 
#1: 1  AB  235   601 
#2: 2  BC  987   987 
#3: 3  AB  366   601 
#4: 4  CD  287   287 

或者使用base R

df1$sum.category <- with(df1, ave(quantity, category, FUN=sum)) 
3

您可以使用tapply得到的款项,然后我们查找表来创建新的列

# use tapply to get the sums. using with() makes the code nicer, IMO. 
cat_sums <- with(df, tapply(quantity, category, sum)) 
# use lookup table to create new column 
df$sum.category <- cat_sums[df$category] 
# id category quantity sum.category 
#1 1  AB  235   601 
#2 2  BC  987   987 
#3 3  AB  366   601 
#4 4  CD  287   287 
3

下面是一个dplyr解决方案

df %>% 
    group_by(category)     %>% # Group by category 
    mutate(sum.category = sum(quantity)) %>% # Sum by category 
    ungroup         # Remove grouping 
#Source: local data frame [4 x 4] 
# 
#  id category quantity sum.category 
# (int) (chr) (int)  (int) 
#1  1  AB  235   601 
#2  2  BC  987   987 
#3  3  AB  366   601 
#4  4  CD  287   287 

ungroup不是绝对必要的。

2

你可以使用相同的合并和汇总在一点点更可读的方式。将实际的df合并到左外部连接all.x = TRUE上将会完成这项工作。我希望这更好理解。

df <- data.frame(id=c(01,02,03,04),category=c("AB","BC","AB","CD"), 
       quantity=c(235,987,366,287)) 

df <- merge(df,aggregate(quantity ~ category, data=df, sum),"category",all.x = TRUE) 
names(df)[4] <- "sum.category" 
df 

# category id  quantity.x sum.category 
#   AB 1  235  601 
#   AB 3  366  601 
#   BC 2  987  987 
#   CD 4  287  287 

如果你还想要一个更易于理解的方式,那么sql是最好的选择。为此,您可能需要sqldf库。我们正在做同样的聚合,并以sql方式合并回实际的df。它更像是一个自我加入的事物。和SQL代码相当容易理解

library (sqldf) 
dfnew<-sqldf("select a.*,b.sum_quantity 
      from df a left join 
      (select category, sum(quantity) sum_category 
      from df group by 1) b 
      on a.category=b.category") 

dfnew 

# category id quantity sum_category 
#  AB 1  235   601 
#  BC 2  987   987 
#  AB 3  366   601 
#  CD 4  287   287