为R数据框中的记录块创建序列号

时间:2012-11-16 14:03:03

标签: r data.table plyr

我有一个相当大的数据集(根据我的标准),我想为记录块创建一个序列号。我可以使用plyr包,但执行时间非常慢。下面的代码复制了可比较的大小数据帧。

## simulate an example of the size of a normal data frame
N <- 30000
id <- sample(1:17000, N, replace=T)
term <- as.character(sample(c(9:12), N, replace=T))
date <- sample(seq(as.Date("2012-08-01"), Sys.Date(), by="day"), N, replace=T)
char <- data.frame(matrix(sample(LETTERS, N*50, replace=T), N, 50))
val <- data.frame(matrix(rnorm(N*50), N, 50))
df <- data.frame(id, term, date, char, val, stringsAsFactors=F)
dim(df)

实际上,这比我使用的要小一些,因为值通常更大......但这已足够接近了。

这是我机器上的执行时间:

> system.time(test.plyr <- ddply(df, 
+                                .(id, term), 
+                                summarise, 
+                                seqnum = 1:length(id), 
+                                .progress="text"))
  |===============================================================================================| 100%
   user  system elapsed 
  63.52    0.03   63.85 

有没有“更好”的方法呢?不幸的是,我在Windows机器上。

提前致谢。

编辑:Data.table非常快,但我无法正确计算我的序列号。这是我的ddply版本创建的。大多数只在组中有一条记录,但有些记录有2行,3行等等。

> with(test.plyr, table(seqnum))
seqnum
    1     2     3     4     5 
24272  4950   681    88     9 

使用如下所示的data.table,相同的方法产生:

> with(test.dt, table(V1))
V1
    1 
24272 

1 个答案:

答案 0 :(得分:5)

使用data.table

dt = data.table(df)
test.dt = dt[,.N,"id,term"]

这是一个时序比较。我使用N = 3000并在生成数据集时将17000替换为1700

f_plyr <- function(){
  test.plyr <- ddply(df, .(id, term), summarise, seqnum = 1:length(id), 
 .progress="text")
}

f_dt <- function(){
 dt = data.table(df)
 test.dt = dt[,.N,"id,term"]
}

library(rbenchmark)
benchmark(f_plyr(), f_dt(), replications = 10,
  columns = c("test", "replications", "elapsed", "relative"))

data.table将事情加速了170倍

test replications elapsed relative
2   f_dt()           10   0.779    1.000
1 f_plyr()           10 132.572  170.182

另请查看Hadley关于dplyr的最新作品。如果dplyr提供额外的加速,我会不会感到惊讶,因为很多代码都在C中重新编写。

更新:修改了代码,根据马特的评论将length(id)更改为.N