Выходной список из двух связанных кадров данных с foreach в R

Допустим, я хочу использовать foreach в пакете doParallel, чтобы вернуть список из двух фреймов данных разных размеров, как показано ниже:

a<-NULL
b<-NULL
for(i in 1:100){
  a<-rbind(a,data.frame(input=i,output=i/2))
  if(i > 5){
    b<-rbind(b,data.frame(input=i,output=i^2))
  }
}
list(a,b)

Поскольку foreach возвращает объект, нет (по крайней мере для меня) очевидного способа сделать то же самое с foreach.

ПРИМЕЧАНИЕ: это сильно упрощенная версия проблемы, с которой я на самом деле работаю, поэтому решение проблемы с помощью lapply (или чего-то в этом роде) не сработает. Суть моего вопроса в том, как это сделать с foreach.


person NewNameStat    schedule 03.12.2014    source источник


Ответы (2)


Я понял. Вы должны определить свою собственную функцию, которая объединяет списки именно так, как вы хотите.

#takes an arbitrary number of lists x all of which much have the same structure    
comb <- function(x, ...) {  
      mapply(rbind,x,...,SIMPLIFY=FALSE)
}

foreach(i=1:10, .combine='comb') %dopar% {
      a<-rbind(a,data.frame(input=i,output=i/2))
      if(i > 5){
        b<-rbind(b,data.frame(input=i,output=i^2))
      }
      list(a,b)
}
person NewNameStat    schedule 03.12.2014
comment
Мне нравится ваша функция объединения, но я думаю, вам нужно удалить вызовы rbind из тела цикла foreach. Кроме того, если вы используете параметр foreach .multicombine=TRUE, он будет более эффективным, так как comb будет вызываться один раз, а не 9 раз в вашем примере. - person Steve Weston; 05.12.2014
comment
Как мы можем изменить функцию comb, чтобы она возвращала только unique значений? - person Carol; 08.05.2018

Добавление версии rbindlist data.table в ответ NewNameStat:

#takes an arbitrary number of lists x all of which much have the same structure    
comb <- function(x, ...) {  
      mapply(rbind,x,...,SIMPLIFY=FALSE)
}

foreach(i=1:10, 
        .combine=function(x,...) mapply(function(...) data.table::rbindlist(list(...), fill = TRUE),x,...,SIMPLIFY=FALSE)) 
      %dopar% {
      a<-rbindlist(list(a,data.table(input=i,output=i/2)))
      if(i > 5){
        b<-rbindlist(list(b,data.table(input=i,output=i^2)))
      }
      list(a,b)
}
person Adrian Antico    schedule 03.12.2019