Apply function to nested list

I already asked a very similar question, but the situation has changed, and the answer I received is not valid for these "new features"

Previous message:

I am wondering if it is possible to apply the function at different levels of the nested list, rapply applies the function recursively in the list, but at the same level. My question is related to the application of the function at different levels with different lengths. Example to illustrate:

 list <- list(list(a=1:5, b=5:9, c=6:10, d=1:5), list(e=2:6, f=3:7, g=8:12), list(h=3:7, i=6:10, j=11:15, k=2:6), list(l=4:8, m=2:6), list(n=5:9, o=1:5, p=2:6, q=0:4), list(r=6:10, s=3:7, t=9:13)) 

I would like to apply a function, such as sum , to the first elements (for example, [[1]]$a=1, [[1]]$b=5, [[1]]$c=6, [[1]]d=1 , and then to the second (for example, [[1]]$a=2, [[1]]$b=6, [[1]]$c=7, [[1]]$d=2) , etc. The result should be something like this:

 [[1]] 13 17 21 25 29 [[2]] 13 16 19 22 25 [[3]] 22 26 30 34 38 [[4]] 6 8 10 12 14 [[5]] 8 12 16 20 24 [[6]] 18 21 24 27 30 

Perhaps a combination of rapply and mapply ?

thanks

A new message:

@ G.Grothendieck already gave me a good solution for this pursuit, but I have another list with pvalues ​​where I would like to apply more complex functions, for example. mean or other functions such as:

 Fisher.test <- function(p) { Xsq <- -2*sum(log(p)) p.val <- 1-pchisq(Xsq, df = 2*length(p)) return(p.val) } 

Reduction does not work, as when using functions such as sum or f="+" , any sentences

Here is an example of what this new list looks like:

 pval.list <- list(list(a=c(0.05, 0.0001, 0.32, 0.45), b=c(0.1,0.12,0.01,0.06), c=c(0.1,0.12,0.01,0.06), d=c(0.01,0.02,0.03,0.04)), list(e=c(0.04, 0.1, 0.232, 0.245), f=c(0.05, 0.01, 0.22, 0.54), g=c(0.005, 0.1, 0.032, 0.045)), list(h=c(0.03, 0.01, 0.12, 0.4), i=c(0.5, 0.0001, 0.132, 0.045), j=c(0.005, 0.0001, 0.0032, 0.045), k=c(0.5, 0.1, 0.932, 0.545)), list(l=c(0.022, 0.0012, 0.32, 0.45), m=c(0.0589, 0.0001, 0.0032, 0.0045)), list(n=c(0.051, 0.01, 0.32, 0.45), o=c(0.05, 0.0001, 0.32, 0.45), p=c(0.05, 0.0001, 0.32, 0.45), q=c(0.05, 0.0001, 0.32, 0.45)), list(r=c(0.053, 0.001, 0.32, 0.45), s=c(0.05, 0.0001, 0.32, 0.45), t=c(0.05, 0.0001, 0.32, 0.45))) 
+4
source share
4 answers

Although Reduce cannot be applied directly using Fisher.test , it can be applied using cbind , and then Fisher.test can be applied to it:

 > lapply(lapply(pval.list, Reduce, f = cbind), apply, 1, Fisher.test) [[1]] [1] 1.953968e-03 2.999509e-05 5.320831e-04 1.339104e-02 [[2]] [1] 0.0007878665 0.0052625525 0.0457435481 0.1146067577 [[3]] [1] 8.982382e-03 3.055250e-08 1.064109e-02 5.094879e-02 [[4]] [1] 9.911091e-03 2.032293e-06 8.073256e-03 1.458443e-02 [[5]] [1] 2.357950e-03 6.135981e-11 3.326486e-01 6.038488e-01 [[6]] [1] 6.597414e-03 3.470933e-09 3.362226e-01 5.708789e-01 

ADDED:

This can be slightly reduced with simplify2array as follows:

 lapply(lapply(pval.list, simplify2array), apply, 1, Fisher.test) 

or using data.frame as follows:

 lapply(lapply(pval.list, data.frame), apply, 1, Fisher.test) 
+3
source

You can use:

 lapply(pval.list, function(x){apply(do.call(rbind, x), 2, Fisher.test)}) [[1]] [1] 1.953968e-03 2.999509e-05 5.320831e-04 1.339104e-02 [[2]] [1] 0.0007878665 0.0052625525 0.0457435481 0.1146067577 [[3]] [1] 8.982382e-03 3.055250e-08 1.064109e-02 5.094879e-02 [[4]] [1] 9.911091e-03 2.032293e-06 8.073256e-03 1.458443e-02 [[5]] [1] 2.357950e-03 6.135981e-11 3.326486e-01 6.038488e-01 [[6]] [1] 6.597414e-03 3.470933e-09 3.362226e-01 5.708789e-01 
+3
source

Will the following work for you?

My solutions use nested lapply

1.

 lapply(lapply(list, function(l)do.call(rbind, l)), colSums) 

2.

 lapply(lapply(pval.list, function(l)do.call(rbind, l)), apply, 2, Fisher.test ) 
+1
source

Perhaps this can be done even faster with the plyr package, but the following works well. First create a new list in which internal lists are converted to matrices

 new.pval.list <- vector('list', length(pval.list)) for (i in 1:length(pval.list)) { nc <- length(unlist(pval.list[[i]] [1])) new.pval.list [[i]] <- matrix(unlist(pval.list[[i]]), ncol = nc, byrow = T) } 

We can use the apply function for each element of the new list using matrices

 lapply(new.pval.list, function(mat) apply(mat, 2, Fisher.test)) 
0
source

Source: https://habr.com/ru/post/1482397/


All Articles