Есть ли быстрый способ перебора комбинаций, подобных тем, которые возвращают expand.grid
или CJ
(data.table
). Когда комбинаций достаточно, они становятся слишком большими, чтобы поместиться в памяти. В библиотеке itertools2
есть iproduct
(порт itertools Python), но он очень медленный (по крайней мере, так, как я его использую, как показано ниже). Есть ли другие варианты?
Вот пример, в котором идея состоит в том, чтобы применить функцию к каждой комбинации строк из двух data.frames
(предыдущий пост).
library(data.table) # CJ
library(itertools2) # iproduct iterator
library(doParallel)
## Dimensions of two data
dim1 <- 10
dim2 <- 100
df1 <- data.frame(a = 1:dim1, b = 1:dim1)
df2 <- data.frame(x= 1:dim2, y = 1:dim2, z = 1:dim2)
## function to apply to combinations
f <- function(...) sum(...)
## Too big to expand with bigger dimensions (ie, 1e6, 1e5) -> errors
## test <- expand.grid(seq.int(dim1), seq.int(dim2))
## test <- CJ(indx1 = seq.int(dim1), indx2 = seq.int(dim2))
## Error: cannot allocate vector of size 3.7 Gb
## Create an iterator over the cartesian product of the two dims
it <- iproduct(x=seq.int(dim1), y=seq.int(dim2))
## Setup the parallel backend
cl <- makeCluster(4)
registerDoParallel(cl)
## Run
res <- foreach(i=it, .combine=c, .packages=c("itertools2")) %dopar% {
f(df1[i$x, ], df2[i$y, ])
}
stopCluster(cl)
## Expand.grid results (different ordering)
expgrid <- expand.grid(x=seq(dim1), y=seq(dim2))
test <- apply(expgrid, 1, function(i) f(df1[i[["x"]],], df2[i[["y"]],]))
all.equal(sort(test), sort(res)) # TRUE
rowSums
здесь очевидный первый шаг:rs1 <- rowSums(df1); rs2 <- rowSums(df2); res2 <- outer(rs1,rs2,"+")
Чтобы проверить ...sum(res-c(t(res2))) # 0
Я не думаю, что распараллеливание очень полезно, когда каждая задача очень мала. - person Frank   schedule 06.07.2015data.frame
на куски таким образом, чтобы результатexpand.grid
самого большого data.frame и фрагмента другого был управляемым. Затем я перебирал все куски. - person nicola   schedule 06.07.2015