0

我想使用 ffdf 完成以下操作:合并列 X 和 Y 以及最接近的时间,然后合并关闭列 B。但是,我在较小的样本中知道的过程涉及使用外部合并(如下所示)。对于不适合内存的大样本(并且可能不适用于 sqldf),使用 ffbase 有什么方法可以解决这个问题?如果不可能,那么最好的图书馆是什么?

作为可重现的示例,如下所示:

set.seed(1)
df.ff <- as.ffdf(cbind(expand.grid(x = 1:3, y = 1:5), time = round(runif(15) * 30)))

to.merge.ff <- as.ffdf(data.frame(x = c(2, 2, 2, 3, 2), y = c(1, 1, 1, 5, 4), time = c(17, 12, 11.6, 22.5, 2), val = letters[1:5], stringsAsFactors = F))

我在这里从@ChinmayPatil 借用以下示例以突出显示我想遵循的类似过程:(R - 在匹配 A、B 和 *closest* C 时合并数据帧?):

require(data.table)
set.seed(1)
df <- setDT(cbind(expand.grid(x = 1:3, y = 1:5), time = round(runif(15) * 30)))

to.merge <- setDT(data.frame(x = c(2, 2, 2, 3, 2), y = c(1, 1, 1, 5, 4), time = c(17, 12, 11.6, 22.5, 2), val = letters[1:5], stringsAsFactors = F))

## First do a left outer merge
A <- merge(to.merge,df, by = c('x','y'), all.x = T )

## Then calculate a diff row as such
A$diff <- abs(A$time.x - A$time.y)

##then take the minimum distance
A[ , .I[which.min(diff)] , by = c('x', 'y' ) ]
4

1 回答 1

0

鉴于我的问题得到的意见很少而且没有答案,我将描述我想出的解决这个问题的方法,希望有人会发现它有用(或者甚至对我来说,作为以后以后的提醒):

对我来说,在一个列上执行此匹配然后在另一列上执行最近匹配的最困难的方面是我一直认为进行外部连接(如帖子中所述)是必要的。使用 data.table 和 ffdfdply 的解决方案非常简单。出于说明的目的,假设有一个大的 ffdf 对象和一个适合内存的常规 data.table

### Large ffdf object    
A <- as.ffdf(data.table( dates.A = seq.Date(as.Date('2008-01-01'),as.Date('2008-01-31'), by = '3 days'), 
                     letters.A = LETTERS[1:4] , value.A = runif(4) ))

### Small data.table that fits in memory
B <- data.table( date.B = seq.Date(as.Date('2008-01-01'),as.Date('2008-01-05'), by = 'days'), 
                 letters.B = LETTERS[1:4] , value.B = runif(4) )

然后,您可以简单地定义一个使用 data.table 和 roll = 'nearest' 进行合并的函数:

merge.ff <- function(x){
setDT(x)
x[, ':=' (dates.merge = dates.A, letters.merge = letters.A)]
B[, ':=' (dates.merge = date.B, letters.merge = letters.B)]
setkeyv(x, c('letters.merge','dates.merge'))
setkeyv(B, c('letters.merge','dates.merge'))

as.data.frame(B[x, roll = 'nearest'])
}

并将其应用于 A:

result <- ffdfdply( A, split = A$dates.A, FUN = merge.ff)

关键只是本质上使用 data.table 中的 roll 方法并将其传递给 ffdfdply。这似乎非常有效。

于 2017-01-25T23:11:18.863 回答