我对tapply
的速度提升有多大的印象,我感到非常震惊 - 就像使用data.table
与数据帧相比的操作一样。
例如:
df = data.frame(class = round(runif(1e6,1,1000)), x=rnorm(1e6))
DT = data.table(df)
# takes ages if somefun is complex
res1 = tapply(df$x, df$class, somefun)
# takes much faster
setkey(DT, class)
res2 = DT[,somefun(x),by=class]
然而,我并没有完全让它比apply
中的数据帧明显更快地工作 - 就像操作一样(即需要将函数应用于每一行的情况)。
df = data.frame(x1 = rnorm(1e6), x2=rnorm(1e6))
DT = data.table(df)
# takes ages if somefun is complex
res1 = apply(df, 1, somefun)
# not much improvement, if at all
DT[,rowid:=.I] # or: DT$rowid = 1:nrow(DT)
setkey(DT, rowid)
res2 = DT[,somefun1(x1,x2),by=rowid]
这真的只是预期还是有一些技巧?
答案 0 :(得分:5)
如果你无法对你的函数进行矢量化(因为递归...),那么你就属于Rcpp
领域。
使用Rcpp
和data.table
的常规规则是
data.table
setkey
...)C?C++
函数说f
,其中包含Rcpp::DataFrame
并返回Rcpp::List
cppOutList <- f(DT)
,DT[,names(cppOutList):=cppOutList]
这样做通常可以让您节省数量级
答案 1 :(得分:0)
使用set
可以大大提高行方式操作的速度。这里有一个很好的基准:Row operations in data.table using `by = .I`