R data.table是否可以对任意函数进行连接(即模糊/软连接)?
以下是假设性的。假设我有一个字符串相似性函数,它生成一个布尔结果(R data.table是否可以对任意函数进行连接(即模糊/软连接)?,r,data.table,R,Data.table,以下是假设性的。假设我有一个字符串相似性函数,它生成一个布尔结果(string\u sim),另一个函数确定两个纬度/经度坐标之间的距离是否低于阈值(geo\u dist) 我决定在这些条件下使用模糊连接进行合并: merge(LHS, RHS, by=string_sim(LHS$string, RHS$string) & geo_dist(LHS$lat, LHS$lon, RHS$lat,RHS$lon)) 在引擎盖下,data.table需要比较笛卡尔积…每一行与每一行不对称。
string\u sim
),另一个函数确定两个纬度/经度坐标之间的距离是否低于阈值(geo\u dist
)
我决定在这些条件下使用模糊连接进行合并:
merge(LHS, RHS, by=string_sim(LHS$string, RHS$string) & geo_dist(LHS$lat, LHS$lon, RHS$lat,RHS$lon))
在引擎盖下,data.table需要比较笛卡尔积…每一行与每一行不对称。对于中等规模的数据集来说,这可能是一个巨大的数字,以万亿计。因此,在向比较函数发送数据时,可能还需要使用分而治之的策略,利用多个进程,每个进程的单元格数不超过20亿,以避免整数限制。本质上,它需要将向量的各个部分映射为片段,然后将它们发送给函数(这听起来像是MAP reduce)
假设用户明智地使用join命令,并希望通过迭代应用join命令来节省时间,从运行成本最低的命令开始,例如相等条件
merge(LHS, RHS, by=list(LHS$first_initial == RHS$first_initial, string_sim(LHS$string, RHS$string) & geo_dist(LHS$lat, LHS$lon, RHS$lat,RHS$lon)))
我想要一个这样的功能。这花了我一些时间,但我已经用data.table拼凑了一些代码来实现这一点,这个包将来可能会有类似的东西
编辑:
让我用一种更具data.table特性的方式来表达这一点。首先定义要匹配的相等变量:
setkey(LHS, first_initial)
setkey(RHS, first_initial)
然后通过矢量扫描执行二进制合并:
LHS[RHS][string_sim(string, string.1) & geo_dist(lat, lon, lat.1,lon.1)]
或者,可以先进行最昂贵的操作。我认为以下几点会更快:
LHS[RHS][geo_dist(lat, lon, lat.1,lon.1)][string_sim(string, string.1)]
但是,当LHS为2000万行,RHS为2000万行时,这可能会使系统过载。为了防止这种情况,我需要使用分治方法将LHS和RHS拆分为多个部分。如果有更有效的方法在后端并行化进程,我想我不必做所有这些
代码如下:
joiner <- function(x,y, reduce=quote( x[map$x][y[map$y],nomatch=0] ), chunks = 100000, mc.cores = getOption("cores")){
require("multicore")
require("data.table")
map_function <- function(x_N,y_N, chunks){
x_partitions = ceiling(x_N/chunks)
x_parts = (0:x_partitions)*chunks
x_parts[length(x_parts)]=x_N
y_partitions = ceiling(y_N/chunks)
y_parts = (0:y_partitions)*chunks
y_parts[length(y_parts)]=y_N
MAP = vector("list",x_partitions*y_partitions )
index = 0
for(i in 1:x_partitions){
for(j in 1:y_partitions){
index = index +1
MAP[[index]] = list(
x = (x_parts[i]+1):x_parts[i+1],
y = (y_parts[j]+1):y_parts[j+1]
)
}
}
return(MAP)
}
if(missing(y)){
y=x
}
reducer_function <- function(map, reduce, x,y){
eval(reduce)
}
collector = mclapply(map_function(nrow(x),nrow(y),chunks=chunks),reducer_function,reduce, x,y, mc.cores=mc.cores)
collector = rbindlist(collector)
return(collector)
}
D = data.table(value=letters, row_id = sample(1:100,26)); D= rbind(D,D); setkey(D,value)
joiner(D); joiner(D,chunks=10); D[D] # they are all the same, except the key is gone
joiner我还没有完全了解,但是我运行了这个示例,它很有效,谢谢。我现在应该增加哪个数字来重现您提交的内存泄漏?示例代码不再有效,因为多核现在是并行的,OP中关于“过载”的问题(在@MatthewDowle提到的bug报告中)已于2012年11月解决。我认为可以肯定地说,这是“太本地化了”。