13

R に非常に大きなデータフレームがあり、他の列の個別の値ごとに 2 つの列を合計したいと考えています。

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 列、合計したい約 100,000 の一意の行)、コードの実行に時間がかかり、最終的にはメモリが不足していると言います。

これを行う最も効率的な方法を知っている人はいますか。

前もって感謝します!

4

4 に答える 4

18

**必須のデータ表の回答**

> 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 
> 
于 2012-08-02T17:13:44.787 に答える
5

これを行う最もきちんとした方法はdplyr

library(dplyr)
shop %>% 
  group_by(shop_id, shop_name, city) %>% 
  summarise_all(sum)
于 2018-12-10T17:50:56.887 に答える
4

ベース 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 秒です。

于 2012-08-02T18:03:32.037 に答える
2

念のため、列のリストが長い場合は、summary_if() を使用します

データ型が int の場合、すべての列を要約します

library(dplyr)
shop %>% 
  group_by(shop_id, shop_name, city) %>% 
  summarise_if(is.integer, sum)
于 2019-02-07T13:37:41.537 に答える