将函数应用于嵌套列表

时间:2013-05-23 13:27:30

标签: r

我已经发布了一个非常相似的问题,但情况发生了变化,我得到的答案对于这些“新特征”无效

较早的帖子:

我想知道是否可以在嵌套列表的不同级别应用函数,rapply在列表中递归地应用函数但在同一级别。我的问题涉及在不同级别应用不同长度的函数。举例说明:

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))

我想将一个函数(例如sum)应用于第一个元素(例如[[1]]$a=1, [[1]]$b=5, [[1]]$c=6, [[1]]d=1,然后应用于第二个元素(例如[[1]]$a=2, [[1]]$b=6, [[1]]$c=7, [[1]]$d=2)等等)。结果应该是这样的:

[[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

也许是rapplymapply的组合?

由于

新帖子

@G.Grothendieck已经为这个追逐提供了一个很好的解决方案,但是,我还有其他pvalues列表,我希望应用更复杂的函数,例如: mean或其他功能,例如:

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

Reduce不能像sumf="+"这样的函数一样工作,有什么建议吗?

以下是此新列表如何显示“

的示例
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 个答案:

答案 0 :(得分:3)

您可以使用:

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

答案 1 :(得分:3)

虽然Reduce无法直接应用Fisher.test,但可以cbind应用Fisher.test,然后可以应用> 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

simplify2array

增加:

使用lapply(lapply(pval.list, simplify2array), apply, 1, Fisher.test) 可以稍微缩短一下:

data.frame

或像这样使用lapply(lapply(pval.list, data.frame), apply, 1, Fisher.test)

{{1}}

答案 2 :(得分:1)

以下是否适用于您?

我的解决方案使用嵌套的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 )

答案 3 :(得分:0)

使用plyr包可能会更快完成,但以下情况很有效。首先创建一个新列表,其中内部列表转换为矩阵

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)
}

我们可以使用apply函数将新列表的每个元素与矩阵

一起使用
lapply(new.pval.list, function(mat) apply(mat, 2, Fisher.test))