2012-08-02 159 views
8

我在R中有一個非常大的數據框,並且想要爲其他列中每個不同值的兩列進行求和,例如我們有一天中各個商店中的交易數據幀的數據如下R中不同列值的總和

shop <- data.frame('shop_id' = c(1, 1, 1, 2, 3, 3), 
    'shop_name' = c('Shop A', 'Shop A', 'Shop A', 'Shop B', 'Shop C', 'Shop C'), 
    'city' = c('London', 'London', 'London', 'Cardiff', 'Dublin', 'Dublin'), 
    'sale' = c(12, 5, 9, 15, 10, 18), 
    'profit' = c(3, 1, 3, 6, 5, 9)) 

是:

shop_id shop_name city  sale profit 
    1  Shop A  London 12 3 
    1  Shop A  London 5 1 
    1  Shop A  London 9 3 
    2  Shop B  Cardiff 15 6 
    3  Shop C  Dublin 10 5 
    3  Shop C  Dublin 18 9 

而且我要總結每個店鋪的銷售和利潤給:

shop_id shop_name city  sale profit 
    1  Shop A  London 26 7 
    2  Shop B  Cardiff 15 6 
    3  Shop C  Dublin 28 14 

我目前使用下面的代碼來做到這一點:

shop_day <-ddply(shop, "shop_id", transform, sale=sum(sale), profit=sum(profit)) 
shop_day <- subset(shop_day, !duplicated(shop_id)) 

這工作絕對沒問題,但我說我的數據框大(140,000行,37列和近10萬的唯一行,我想總結)而且我的代碼需要很長時間才能運行,然後最終表明它的內存不足。

有誰知道最有效的方法來做到這一點。

在此先感謝!

+2

......我覺得'data.table'的答案來了...... – 2012-08-02 16:42:40

回答

13

**強制性數據表的答案**

> library(data.table) 
data.table 1.8.0 For help type: help("data.table") 
> shop.dt <- data.table(shop) 
> shop.dt[,list(sale=sum(sale), profit=sum(profit)), by='shop_id'] 
    shop_id sale profit 
[1,]  1 26  7 
[2,]  2 15  6 
[3,]  3 28  14 
> 

直到事情得到更大這聽起來很好,很好......

shop <- data.frame(shop_id = letters[1:10], profit=rnorm(1e7), sale=rnorm(1e7)) 
shop.dt <- data.table(shop) 

> system.time(ddply(shop, .(shop_id), summarise, sale=sum(sale), profit=sum(profit))) 
    user system elapsed 
    4.156 1.324 5.514 
> system.time(shop.dt[,list(sale=sum(sale), profit=sum(profit)), by='shop_id']) 
    user system elapsed 
    0.728 0.108 0.840 
> 

如果創建data.table你獲得額外的速度增加用鑰匙:

shop.dt <- data.table(shop, key='shop_id') 

> system.time(shop.dt[,list(sale=sum(sale), profit=sum(profit)), by='shop_id']) 
    user system elapsed 
    0.252 0.084 0.336 
> 
+0

請注意,Justin在他的'ddply'調用中使用'summarise'而不是'transform';這種改變可能足以讓你的代碼在沒有內存錯誤的情況下工作,儘管其他解決方案肯定更快。 – Aaron 2012-08-02 17:52:39

+0

@Aaron謝謝!因爲有一個較早的答案解釋了它,所以我留下了這個解釋。不過那是自從刪除! – Justin 2012-08-02 17:56:10

+0

謝謝賈斯汀,快得多。另一個快速問題是,有沒有辦法將其他列(例如shop_name,city)保留在最終的數據表中?我可以重新加入初始數據框來獲取這個數據,但如果在初始查詢中有一種方法可以做到這一點,那麼它會更加整潔。 – user1165199 2012-08-02 17:56:24

3

下面是如何使用基礎R加快操作是這樣的:

idx <- split(1:nrow(shop), shop$shop_id) 
a2 <- data.frame(shop_id=sapply(idx, function(i) shop$shop_id[i[1]]), 
       sale=sapply(idx, function(i) sum(shop$sale[i])), 
       profit=sapply(idx, function(i) sum(shop$profit[i]))) 

對於我的系統上的ddply彙總版本,時間縮短爲0.75秒,而5.70秒。

+0

如果我在上面的例子中有很多列,比如銷售額和利潤,我想總結一下,是否可以調用一個函數來將上面的代碼中的第三行和第四行組合成一行。 – discipulus 2015-05-25 12:39:16

+1

不是真的使用這種確切的方法,但有辦法做到這一點。用一個最小可重現的例子開始一個新的問題,你會得到很多建議。 – Aaron 2015-05-25 23:27:54