Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.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中foreach循环内的data.table结果时出现问题_R_Loops_Foreach_Data.table - Fatal编程技术网

连接R中foreach循环内的data.table结果时出现问题

连接R中foreach循环内的data.table结果时出现问题,r,loops,foreach,data.table,R,Loops,Foreach,Data.table,我正在使用嵌套的foreach循环中的data.table对象,在创建结果对象时遇到了问题 基本上是生成长度(intersect(set1,set2))。我还想生成长度(union(set1,set2))和一些其他指标 以下代码和示例数据: library(iterators) library(data.table) library(foreach) #generate dummy data set.seed(1212) sample1 <- data.frame(parentid=ro

我正在使用嵌套的foreach循环中的data.table对象,在创建结果对象时遇到了问题

基本上是生成长度(intersect(set1,set2))。我还想生成长度(union(set1,set2))和一些其他指标

以下代码和示例数据:

library(iterators)
library(data.table)
library(foreach)

#generate dummy data
set.seed(1212)
sample1 <- data.frame(parentid=round((runif(50000, min=1, max=50000))), childid=round(runif(100000, min=1, max=100000)))
length(unique(sample1$parentid))

#get unique parents
sample1uniq <- as.data.frame(unique(sample1$parentid))
names(sample1uniq) <- "parentid"

#convert original dataset to data.table
sample1 <- data.table(sample1)
setkey(sample1,parentid)

#convert unique ids to data.table
sample1uniq <- data.table(sample1uniq)
setkey(sample1uniq,parentid)

#a random sample of 5K to users to scan against
sample2uniq_idx <- sample(1:nrow(sample1uniq), size=5000)
sample2uniq <- sample1uniq[sample2uniq_idx]
sample2uniq <- data.table(sample2uniq)
setkey(sample2uniq,parentid)

#construct iterators
sample1uniq_iter <- iter(sample1uniq)
sample2uniq_iter <- iter(sample2uniq)
相反,它是一个列表,其中u1和u2是前两个元素,inter是SUM(长度(intersect(set1,set2)))

谢谢你的建议…

解决方案 您的主要问题是迭代器。请记住,数据表被许多事物(例如迭代器)视为列表,因此您生成的两个迭代器将每个迭代器只迭代一项,即每个数据表中的单个列。如果您仔细观察您的结果:

> str(outerresults)
List of 3
 $ u1   : num [1:31602] 2 3 5 6 7 8 10 11 12 14 ...
 $ u2   : num [1:5000] 14 26 27 31 34 61 68 81 99 106 ...
 $ inter: int 14778
u1基本上只是
sample1unique
,u2是
sample2unique
,inter是:

> length(intersect(sample1[J(sample1uniq)][,childid], sample1[J(sample2uniq)][,childid]))
[1] 14778
换句话说,你实际上根本没有循环过任何东西

另一个问题是,这种方法(一旦解决了上述问题)非常缓慢。通过对列表进行大约160MM次的RBIND操作,您正在生长一个非常大的对象。这是个坏消息。我修复了它(更改了迭代器),并以更小的大小运行它,以给您一个想法(100 x 20,或原始大小的1/8000):


相同的结果,但快了25倍(尽管注意data.table版本只报告sample1-sample2的独特组合)。

还不完全清楚您要计算什么。
merge(…)
的输出是一个data.table,因此您可以在它之后使用daisychain
[
,即:
merge(…)[,list(intersect=.N,union=length(unique(childid))]
等。我可能不完全理解您的示例,但如果每次迭代的输出都是
数据表
,那么我认为您需要将
更改为
合并为
c
(默认值将返回列表中的结果)然后在结果上使用
rbindList
将列表中的所有数据表一起绑定到
rbind
。@SimonO101:我现在更改了问题,希望现在更清楚。感谢您的帮助。对于搜索此主题的任何人,请给出一个简短的提示。
foreach
说明:
%
运算符是嵌套运算符,已使用用于创建嵌套的
foreach
循环。键入
vignette(“嵌套”)
在R提示下获取更多详细信息。谢谢@BrodieG,但我不确定catesian将一个40M数据集连接到自身是否适用于我。另外,放弃并行化循环意味着我没有利用问题的并行性质。我相信你的循环相当于笛卡尔连接。并行化是一个问题,但可能有办法解决分解问题,并将每个问题作为data.table问题处理。此外,除了不同的实现之外,我相信我已经回答了您最初的问题,解释了为什么您的实现没有按预期工作。如果我错了,请纠正我。是的,是的,是的,如果我没有给予您应有的信任,我很抱歉。再次感谢。您介意吗按当时的回答回答这个问题?谢谢。
> str(outerresults)
List of 3
 $ u1   : num [1:31602] 2 3 5 6 7 8 10 11 12 14 ...
 $ u2   : num [1:5000] 14 26 27 31 34 61 68 81 99 106 ...
 $ inter: int 14778
> length(intersect(sample1[J(sample1uniq)][,childid], sample1[J(sample2uniq)][,childid]))
[1] 14778
#generate dummy data
set.seed(1212)
sample1 <- data.frame(parentid=round((runif(50, min=1, max=50))), childid=round(runif(100, min=1, max=100)))
length(unique(sample1$parentid))

#get unique parents
sample1uniq <- as.data.frame(unique(sample1$parentid))
names(sample1uniq) <- "parentid"

#convert original dataset to data.table
sample1 <- data.table(sample1)
setkey(sample1,parentid)

#convert unique ids to data.table
sample1uniq <- data.table(sample1uniq)
setkey(sample1uniq,parentid)

#a random sample of 5K to users to scan against
sample2uniq_idx <- sample(1:nrow(sample1uniq), size=20)
sample2uniq <- sample1uniq[sample2uniq_idx]
sample2uniq <- data.table(sample2uniq)
setkey(sample2uniq,parentid)

# Notice how we don't use iterator objects

outerresults <- foreach (x = sample1uniq$parentid, .combine=rbind, .packages=c('foreach','doParallel', 'data.table')) %dopar% {
  b <- sample1[J(x)]                          #ith parent
  b2 <- as.data.frame(b)[,2]  #ith parent's children

  results <- foreach (y = sample2uniq$parentid, .combine=rbind) %dopar% {
    c <- sample1[J(y)]                          #jth parent
    c2 <- as.data.frame(c)[,2]  #jth parent's children

    common <- length(intersect(b2, c2))

    results <- list(u1=x, u2=y, inter=common)
    results
  }
}
#  user  system elapsed 
#  1.57    0.00    1.60 
head(outerresults)
#         u1 u2 inter
# result.1 2  2  4    
# result.2 2  4  0    
# result.3 2  7  0    
# result.4 2  7  0    
# result.5 2  8  2    
# result.6 2  8  2        
# Prepare data in two data tables

vec.samp1 <- par.ids             # exact copy of what we generated earlier
vec.samp1.child <- child.ids     # exact copy of what we generated earlier
dt.s1 <- data.table(sample1=vec.samp1, sample1.child=vec.samp1.child, key="sample1")

vec.samp2 <- sample2.ids         # exact copy of what we generated earlier
dt.s2 <- dt.s1[data.table(sample2=vec.samp2)]
setnames(dt.s2, c("sample2", "sample2.child"))

# Create the cartesian join of our data sets and then
# join to get the child values

combinations <- CJ(sample1=vec.samp1, sample2=vec.samp2)
setkey(combinations, "sample1")
combinations <- combinations[dt.s1, allow.cartesian=T]
setkey(combinations, "sample2")
combinations <- combinations[dt.s2, allow.cartesian=T]

# Compute intersect and union

combinations[order(sample1, sample2), 
  list(
    intersect=length(intersect(sample1.child, sample2.child)),
    union=length(union(sample1.child, sample2.child))
  ),
  by=list(sample1, sample2)
]
#    user  system elapsed 
#    0.06    0.00    0.06 

#    sample1 sample2 intersect union
# 1:       2       2         4     4
# 2:       2       4         0     6
# 3:       2       7         0    10
# 4:       2       8         2    10
# 5:       2       9         0     6