R 分组汇总,应用涉及下一组的功能

R 分组汇总,应用涉及下一组的功能,r,dataframe,data.table,dplyr,R,Dataframe,Data.table,Dplyr,假设我有以下数据: set.seed(1) test <- data.frame(letters=rep(c("A","B","C","D"),10), numbers=sample(1:50, 40, replace=TRUE)) 其中: > notIn A B C 9 7 7 但我也希望使用dplyr或data.table来实现这一点。可能吗?瓶颈似乎在拆分中。当对200个组和每个组150000个观察值进行模拟时,split在总共54秒中花费50秒 使用数据可以大大加快拆

假设我有以下数据:

set.seed(1)
test <- data.frame(letters=rep(c("A","B","C","D"),10), numbers=sample(1:50, 40, replace=TRUE))
其中:

> notIn
A B C 
9 7 7 

但我也希望使用
dplyr
data.table
来实现这一点。可能吗?

瓶颈似乎在
拆分中。当对200个组和每个组150000个观察值进行模拟时,
split
在总共54秒中花费50秒

使用
数据可以大大加快拆分
步骤。表
如下所示

## test is a data.table here
s.test <- test[, list(list(.SD)), by=letters]$V1

这大约是最大数据维度的7.5倍加速。这是否足够?

这似乎提供了与data.table相同的加速比,但只使用基数R。它不拆分数据帧,而是只拆分数字列(在标有###的行中):

##生成数据-来自Arun的帖子
结实种子(1L)
k=200L
n=150000升

测试我不认为这可以用plyr优雅地完成。看看这个答案和我在评论中与哈德利(普莱尔的作者)的讨论。因此,唯一的方法会有点低效:对于每个字母,您必须将整个
测试
数据子集以找到下一个字母。基本代码的小改进:
mapply(函数(x,y)sum(!x$numbers%in%y$numbers),head(s.test,-1),tail(s.test,-1))
Nice,我没有想到使用head/tails,它看起来确实更优雅。但我仍然希望有一个
dplyr
数据表
解决方案,因为我的真实数据集非常大,所以速度会有所帮助(虽然我不确定它们是否真的更快,但我必须进行测试)。在实际数据中,
字母
列中有多少唯一值?到底有多大才是真正的大呢?现在我有大约200个小组,每个小组5000次观察。但这是一个正在进行的分析,数据每天都在变大。我的第一个想法是,考虑到他们想对数据做什么,以宽格式存储可能更有意义,而不是长格式,甚至只是一个简单的列表,因为这样你就完全避免了拆分,data.table或no。如果他们提前存储数据,我想知道一个简单的循环通过列的速度会有多快。是的,+1,我在真实的data.frame上进行了测试,这个速度真的很快@joran今天,数据已经以这种形式收集,也许将其转换为宽格式可能会有所帮助,但我不确定(因为我必须多次这样做),我会尝试一下。你不能用交叉连接来解决这个问题吗?@hadley,我看不出一个明显的方法。你打算怎么做?@arun我的直觉是你可以做一个自交叉连接,去掉两边行相同的情况,然后
setdiff
变量。
## test is a data.table here
s.test <- test[, list(list(.SD)), by=letters]$V1
## generate data
set.seed(1L)
k = 200L
n = 150000L
test <- data.frame(letters=sample(paste0("id", 1:k), n*k, TRUE), 
                 numbers=sample(1e6, n*k, TRUE), stringsAsFactors=FALSE)

require(data.table)   ## latest CRAN version is v1.9.2
setDT(test)           ## convert to data.table by reference (no copy)
system.time({
    s.test <- test[, list(list(.SD)), by=letters]$V1 ## split
    setattr(s.test, 'names', unique(test$letters))   ## setnames
    notIn <- mapply(function(x,y) 
         sum(!s.test[[x]]$numbers %in% s.test[[y]]$numbers), 
              x=names(s.test)[1:199], y=names(s.test)[2:200])
})

##   user  system elapsed 
##  4.840   1.643   6.624 
## generate data - from Arun's post
set.seed(1L)
k = 200L
n = 150000L
test <- data.frame(letters=sample(paste0("id", 1:k), n*k, TRUE), 
                 numbers=sample(1e6, n*k, TRUE), stringsAsFactors=FALSE)

system.time({
    s.numbers <- with(test, split(numbers, letters)) ##
    notIn <- mapply(function(x,y) 
         sum(!s.numbers[[x]] %in% s.numbers[[y]]), 
              x=names(s.numbers)[1:199], y=names(s.numbers)[2:200])
})