0

I would like to combine a list of list which has elements that are arrays and numbers, the array has attributes that I want to conserve and also the dimensions of the array.

# names of rows
pn <-as.list(paste0("P",1:10))

pa <-matrix(runif(100),nrow=10)
rownames(pa)<-pn

pb <-matrix(runif(100),nrow=10)
rownames(pb)<-pn

a<-list(list(nsim=runif(1),param=pa),list(nsim=runif(1),param=pb))

I can combine this list into one list like this

a1 <- do.call(Map, c(c, a))

but this is not the result I need, the names of the rows are lost and I want to make different operations for each component, for nsim I want to make a sum, and for param I want to combine by columns like cbind. I think that this could be done with a for loop but I wonder if it could be done faster using a function instead of Map. The result I expect is like this:

pc <-matrix(runif(200),nrow=10)
rownames(pc)<-pn
res<-list(nsim=runif(1)+runif(1),param=pa)

res 


$nsim
[1] 0.3104111

$param
[,1]       [,2]       [,3]       [,4]       [,5]        [,6]      [,7]      [,8]      [,9]
P1  0.2239347 0.06278946 0.98205058 0.61853458 0.02383296 0.002134358 0.8513100 0.5719191 0.5900750
P2  0.8692000 0.12358855 0.16389523 0.70464981 0.28209890 0.595703930 0.1770708 0.7762373 0.5342873
P3  0.3812888 0.78675818 0.58067408 0.75473889 0.26632764 0.665318861 0.4758030 0.4214253 0.1549026
...
[,11]     [,12]     [,13]       [,14]       [,15]     [,16]     [,17]     [,18]      [,19]
P1  0.7276528 0.6331882 0.8154552 0.034903094 0.384146499 0.1222392 0.1048753 0.5124031 0.57319354
P2  0.9089065 0.4261310 0.4903192 0.680854370 0.331368439 0.0239536 0.4988695 0.2384391 0.28938142
P3  0.2615411 0.6219749 0.8196556 0.611008178 0.012309896 0.1656148 0.1684677 0.8212866 0.96902755
...
Leosar
  • 2,010
  • 4
  • 21
  • 32

1 Answers1

2

Based on your description, the following combination of Map and Reduce should work:

 Map(function(f, i) Reduce(f, lapply(a, "[[", i)), list("+", "cbind"), as.list(1:2))

The idea is to map the appropriate functions (+ and cbind) to the appropriate elements of each list. The appropriate list elements are extracted using lapply, [[ and the desired index. These extracted results are then comined using the appropriate function through Reduce.

With a seed of 1234, this returns

[[1]]
[1] 1.189114

[[2]]
           [,1]      [,2]       [,3]      [,4]      [,5]       [,6]       [,7]       [,8]      [,9]     [,10]      [,11]
P1  0.113703411 0.6935913 0.31661245 0.4560915 0.5533336 0.07377988 0.86483383 0.12148019 0.9264005 0.1663938 0.03545673
P2  0.622299405 0.5449748 0.30269337 0.2651867 0.6464061 0.30968660 0.04185728 0.89283638 0.4719097 0.9004246 0.56507611
P3  0.609274733 0.2827336 0.15904600 0.3046722 0.3118243 0.71727174 0.31718216 0.01462726 0.1426153 0.1340782 0.28025778
P4  0.623379442 0.9234335 0.03999592 0.5073069 0.6218192 0.50454591 0.01374994 0.78312110 0.5442698 0.1316141 0.20419632
P5  0.860915384 0.2923158 0.21879954 0.1810962 0.3297702 0.15299896 0.23902573 0.08996133 0.1961747 0.1052875 0.13373890
P6  0.640310605 0.8372956 0.81059855 0.7596706 0.5019975 0.50393349 0.70649462 0.51918998 0.8985805 0.5115836 0.32568192
P7  0.009495756 0.2862233 0.52569755 0.2012480 0.6770945 0.49396092 0.30809476 0.38426669 0.3894998 0.3001991 0.15506197
P8  0.232550506 0.2668208 0.91465817 0.2588098 0.4849912 0.75120020 0.50854757 0.07005250 0.3108708 0.0267169 0.12996214
P9  0.666083758 0.1867228 0.83134505 0.9921504 0.2439288 0.17464982 0.05164662 0.32064442 0.1600287 0.3096474 0.43553106
P10 0.514251141 0.2322259 0.04577026 0.8073523 0.7654598 0.84839241 0.56456984 0.66849540 0.8961858 0.7421197 0.03864265
        [,12]     [,13]     [,14]     [,15]      [,16]      [,17]     [,18]      [,19]     [,20]
P1  0.7133016 0.7442772 0.9622228 0.5027498 0.43904205 0.42944396 0.7572890 0.47880269 0.6389113
P2  0.1007690 0.9159742 0.6340994 0.9836351 0.22859970 0.57587778 0.5842715 0.34483055 0.9925160
P3  0.9503049 0.9945982 0.1274334 0.3243860 0.08215807 0.43250740 0.7088394 0.60071414 0.1282698
P4  0.1218178 0.9423607 0.4230470 0.4813749 0.85026492 0.22484576 0.4269758 0.07608332 0.8832396
P5  0.2196566 0.4861354 0.9143169 0.3569871 0.23466126 0.08498474 0.3435727 0.95599261 0.8100834
P6  0.9130878 0.2834595 0.4677923 0.6274777 0.98816745 0.63729826 0.7591200 0.02220682 0.8218512
P7  0.9458531 0.2515457 0.9081691 0.7416002 0.60189755 0.43101637 0.4240302 0.84171063 0.8347027
P8  0.2791562 0.5032552 0.5977433 0.5659668 0.99874081 0.07271609 0.5608873 0.63244245 0.7327322
P9  0.1234711 0.4969662 0.6317428 0.9807865 0.37559938 0.80240202 0.1161358 0.31009417 0.9830440
P10 0.7971605 0.3184458 0.8691583 0.5768127 0.55512663 0.32527830 0.3030218 0.74256937 0.6392046

Note that you can add names to each list element by wrapping this in setNames.


alexis-laz suggests two cleaner versions of this method, one with do.call, Map , ..., and nested lists.

# put the functions into their own list.
funs = list(`+`, cbind)
do.call(Map, c(function(f, ...) f(...), list(funs), a))

and the other using .mapply, ... and nested lists.

.mapply(function(f, ...) f(...), c(list(funs), a), NULL)
lmo
  • 37,904
  • 9
  • 56
  • 69
  • Using `Map(function(f, i) Reduce(f, lapply(a, "[[", i)), list("+", "cbind"), list(1, 2))` works, but what happen if you have more than two lists?, in fact it could be any number of lists. And how to add the names for each component? – Leosar Apr 26 '17 at 14:11
  • Well, it will depend on what you mean. Thanks to `Reduce`, this will work for nested lists where the inner lists have two elements (of the same structure), regardless of number of elements in the outer lists (ie, the number of nsim-param pairs). If instead of (nsim-param) pairs, you have a triple or larger, tuple, you will have to decide on the list of functions for combination. You can automate the indexing with something like as.list(1:n) where n is the tuple length. – lmo Apr 26 '17 at 14:18
  • 1
    A similar (probably a bit cleaner?) approach could be `funs = list(\`+\`, cbind); do.call(Map, c(function(f, ...) f(...), list(funs), a))` or, perhaps, `.mapply(function(f, ...) f(...), c(list(funs), a), NULL)` – alexis_laz Apr 26 '17 at 14:31
  • @alexis_laz that is a nice solution. If you want to post it separately, I'll upvote it. – lmo Apr 26 '17 at 14:35
  • @lmo : Feel free to add it here -- it 's basically the same concept; I, initially, tried to build something off of your idea – alexis_laz Apr 26 '17 at 15:42
  • If you have more components in the inner list, in fact I have 6, the first seems to be cleaner. – Leosar Apr 26 '17 at 20:21