R数据表用户定义的功能很慢

时间:2018-07-28 18:25:58

标签: r data.table igraph

我有两个数据表dt1dt2dt1由单个指示器ii的列表和时间指示器tt的列表构成。一个有3个人和两个时间段的示例是:

library(data.table)
ii_ind = c(1,2,3)
tt_ind = c(2010,2011)
dt1 = merge(x=data.frame(ii =ii_ind) , y = data.frame(jj=ii_ind))
dt1 = merge(x=dt1 , y = data.frame(tt = tt_ind))
dt1 = as.data.table(dt1)
dt1 = dt1[ii != jj]

dt1代表动态网络中的二元组(边缘的指示器在第四列中,但与我在此处尝试执行的操作无关)。

dt2具有三列,分别指示单个ii,时间tt和整数变量zz。例如:

dt2 = data.table(ii = c(1,1,1,1,1,2,2,2,2,3,3), 
                 tt = c(2010,2010,2011,2011,2011,2010,2010,2011,2011,2010,2011),
                 zz = c(1,2,1,2,3,1,2,1,2,3,3))

我想在dt1中添加一个新列,例如count.zz,以计算(ii,tt)(jj,tt)共有一个zz的实例数。这是我的方法:

setkey(dt1,ii,jj,tt)
setkey(dt2,ii,tt)
dt1[,count.zz:= as.integer(0)]
count.zz.fun = function(z.ii,z.jj,z.tt){
  return(length(intersect(dt2[.(z.ii,z.tt),zz],dt2[.(z.jj,z.tt),zz])))
}
dt1[,count.zz := count.zz.fun(ii,jj,tt), by = c("ii","jj","tt")]

在该示例中,我们为count.zz=2拥有ii=1,jj=2,tt=2010,因为(ii,tt)(jj,tt)共有zz=1zz=2count.zz=0代表ii=1,jj=3,tt=2010,因为zz=1的{​​{1}}和zz=2的{​​{1}}与(ii,tt)的{​​{1}}的集合不相交,即(jj,tt)

我想知道是否有更快的方法。 zzzz=3中有2.3百万行,范围从dt1zz,上述操作大约需要1才能在标准桌面上运行电脑

我已经标记了100,因为上面的结构是一个网络,并且可能使用我不知道的2-3 hours来完成此操作。

@Ryan建议使用igraph而不是igraph。这是两个功能的比较:

sum(a %in% b)

结果:

length(intersect(a,b))

@Ryan的建议将速度提高了13-14%。

1 个答案:

答案 0 :(得分:3)

根据dt2的尺寸,您可能想对dt2执行自连接以生成tt和zz组合的所有ii和jj对。然后执行连接并使用by=.EACHI

计算长度
#find all pairs of ii and jj for combis of tt and zz
reldt <- dt2[dt2, .(ii=x.ii, jj=i.ii, tt, zz), on=.(tt,zz)]

#join and find the number of occurrence
reldt[dt1, on=.(ii,jj,tt), .N, by=.EACHI]

输出:

    ii jj   tt N
 1:  2  1 2010 2
 2:  3  1 2010 0
 3:  1  2 2010 2
 4:  3  2 2010 0
 5:  1  3 2010 0
 6:  2  3 2010 0
 7:  2  1 2011 2
 8:  3  1 2011 1
 9:  1  2 2011 2
10:  3  2 2011 0
11:  1  3 2011 1
12:  2  3 2011 0