Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/76.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R 使用过滤加速data.table笛卡尔积_R_Data.table - Fatal编程技术网

R 使用过滤加速data.table笛卡尔积

R 使用过滤加速data.table笛卡尔积,r,data.table,R,Data.table,给定一个包含三个字段的data.table,provider\u id和srvc\u dt。我需要计算一对提供者看到的不同成员的数量。如果一名成员在180天内访问了两个供应商,则称其访问了这两个供应商。这用于使用#访问阈值构造无向图,并查找连接的组件 我正在使用中建议的方法 我需要运行的实例有超过300万条记录,运行时间超过5分钟。是否有方法重新写入或使用新的data.table函数以使其运行更快 require(data.table) nmem <- 5000 data.dt <

给定一个包含三个字段的
data.table
provider\u id
srvc\u dt
。我需要计算一对提供者看到的不同成员的数量。如果一名成员在180天内访问了两个供应商,则称其访问了这两个供应商。这用于使用#访问阈值构造无向图,并查找连接的组件

我正在使用中建议的方法

我需要运行的实例有超过300万条记录,运行时间超过5分钟。是否有方法重新写入或使用新的data.table函数以使其运行更快

require(data.table)

nmem <- 5000
data.dt <- data.table(member_id=sample(10000:1000000,nmem,replace=TRUE), provider_id=sample(1000:2000,nmem,replace=TRUE),
    srvc_dt=sample(seq(as.Date('2014/01/01'), as.Date('2015/01/01'), by="day"), nmem, replace=TRUE))
setkey(data.dt, member_id)

prov_pair.dt <- data.dt[data.dt, {
        idx = provider_id<i.provider_id & abs(srvc_dt-i.srvc_dt)<180
        list(provider_id1 = provider_id[idx], 
            srvc_dt1 = srvc_dt[idx],
            provider_id2 = i.provider_id[any(idx)],
            srvc_dt2 = i.srvc_dt[any(idx)]
        )
    }, by=.EACHI, allow=TRUE]

prov_pair_agg.dt <- prov_pair.dt[, .(weight=length(unique(member_id))), .(provider_id1,provider_id2)]
require(data.table)

nmem简单的左连接,然后进行过滤:

prov_pair.dt <- data.dt[data.dt,allow.cartesian=T][provider_id<i.provider_id &
  abs(srvc_dt-i.srvc_dt)<180,]

在nmem=1000000的16gb内存计算机上,按您当前的方法,这需要1.487s而不是106.034s。

首先,筛选出数据,以仅包括见过多个提供程序的成员:

res = data.dt[, if (.N >= 2) .SD, by = member_id]
然后,添加日期的端点和提供者列的副本:

res[, `:=`(start.date = srvc_dt - 180,
           end.date   = srvc_dt + 180,
           provider2  = provider_id)]
最后,使用新的非等联接,可在以下目录中找到:

res[res,on=(member\u id=member\u id,provider2start.date)
,allow=T,nomatch=0][,.N,by=(provider1=provider\u id,provider2)]

一个注意事项——不幸的是,上面连接中的列的名称目前有点混乱,希望很快就能解决。如果以上内容太不清楚,您可以添加额外的列副本,以查看到底发生了什么。

请将nmem设置为1000000,然后重试。我得到以下错误
…在2009362行中加入结果;超过2000000=nrow(x)+nrow(i).
。另一种方法的优点是内存效率高(参见@Arun文章的最后一行)。当nmem=1000000时,需要
allow.cartesian=T
,但这种方法仍然很快,提供了足够的内存。可能会过滤掉只看到单个提供者的成员,即从
data.dt[,if(.N>=2)开始.SD,by=member\u id]
,将解决内存问题(当然取决于数据)@webb谢谢。不幸的是,在我启动这个程序之后,我的记忆突然出现了峰值,我的记忆也没有了。我确实看到,对于较小的实例,这要快得多。@eddi谢谢。我在代码中预先过滤掉了这些内容。
res[, `:=`(start.date = srvc_dt - 180,
           end.date   = srvc_dt + 180,
           provider2  = provider_id)]
res[res, on = .(member_id = member_id, provider2 < provider_id,
                srvc_dt < end.date, srvc_dt > start.date)
    , allow = T, nomatch = 0][, .N, by = .(provider1 = provider_id, provider2)]