2016-01-21 71 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