R:在 functions/loops(Extreme Bounds 包)中使用过滤器命令解决列表深处的对象

R: Adress objects deep inside lists with filter commands inside functions/loops (ExtremeBounds package)

我正在使用 ExtremeBounds 包,它提供了一个多级列表,其中(除其他外)数据帧处于最低级别。我 运行 这个包超过了几个规范,我想在这些结果中收集一些选定数据框的列。这些应该按规范(下例中的 spec1 和 spec2)收集并排列在数据帧列表中。然后可以将此数据框列表用于各种用途,例如将不同规范的结果导出到不同的 Excel 表格中。

这是一些创建有问题对象的代码(只是 运行 盲目地使用这段代码,我的问题只涉及如何处理它创建的列表类型:eba_results ):

library("ExtremeBounds")
Data <- data.frame(var1=rbinom(30,1,0.2),var2=rbinom(30,2,0.2),
               var3=rnorm(30),var4=rnorm(30),var5=rnorm(30))
spec1 <- list(y=c("var1"), 
             freevars=c("var2"),
             doubtvars=c("var3","var4"))
spec2 <- list(y=c("var1"), 
          freevars=c("var2"),
          doubtvars=c("var3","var4","var5"))
indicators <- c("spec1","spec2")

ebaFun <- function(x){
eba  <- eba(data=Data, y=x$y, 
     free=x$freevars, 
     doubtful=x$doubtvars,
     reg.fun=glm, k=1, vif=7, draws=50, weights = "lri", family = binomial(logit))}

eba_results <- lapply(mget(indicators),ebaFun) #eba_results is the object in question

手动我知道如何访问每个元素,例如:

eba_results$spec1$bounds$type #look at str(eba_results) to see the different levels

所以 "bounds" 是一个数据框,其中 spec1 和 spec2 的列名相同。我想从 "bounds" 中收集以下 5 列:

类型,cdf.mu.normal,cdf.above.mu.normal,cdf.mu.generic,cdf.above.mu.generic

每个规格放入一个数据帧。手动这很简单但很难看:

collectedManually <-list( 
manual_spec1 = data.frame(
 type=eba_results$spec1$bounds$type, 
 cdf.mu.normal=eba_results$spec1$bounds$cdf.mu.normal,
 cdf.above.mu.normal=eba_results$spec1$bounds$cdf.above.mu.normal,
 cdf.mu.generic=eba_results$spec1$bounds$cdf.mu.generic,
 cdf.above.mu.generic=eba_results$spec1$bounds$cdf.above.mu.generic),
manual_spec2= data.frame(
 type=eba_results$spec2$bounds$type, 
 cdf.mu.normal=eba_results$spec2$bounds$cdf.mu.normal,
 cdf.above.mu.normal=eba_results$spec2$bounds$cdf.above.mu.normal,
 cdf.mu.generic=eba_results$spec2$bounds$cdf.mu.generic,
 cdf.above.mu.generic=eba_results$spec2$bounds$cdf.above.mu.generic))

但我有超过 2 个规范,我认为这应该可以通过 lapply 函数以更漂亮的方式实现。任何帮助将不胜感激!

p.s.: hrbrmstr 的答案适用但结果过于简单的通用示例:

exampleList = list(a=list(aa=data.frame(A=rnorm(10),B=rnorm(10)),bb=data.frame(A=rnorm(10),B=rnorm(10))),
               b=list(aa=data.frame(A=rnorm(10),B=rnorm(10)),bb=data.frame(A=rnorm(10),B=rnorm(10))))

我想要一个对象,例如,将所有 A 和 B 向量收集到两个数据帧(每个数据帧都有其各自的 A 和 B),然后是数据帧列表.手动这看起来像:

dfa <- data.frame(A=exampleList$a$aa$A,B=exampleList$a$aa$B)
dfb <- data.frame(A=exampleList$a$aa$A,B=exampleList$a$aa$B)
collectedResults <- list(a=dfa, b=dfb)

可能有一种不太暴力的方法可以做到这一点。

如果您想要单个列的列表,这是一种方法:

get_col <- function(my_list, col_name) {
  unlist(lapply(my_list, function(x) {
    lapply(x, function(y) { y[, col_name] })
  }), recursive=FALSE)
}

get_col(exampleList, "A")
get_col(exampleList, "B")

如果您想要合并 data.frame 指标列,这是一种方法:

collect_indicators <- function(my_list, indicators) {
  lapply(my_list, function(x) {
    do.call(rbind, c(lapply(x, function(y) { y[, indicators] }), make.row.names=FALSE))
  })[[1]]
}

collect_indicators(exampleList, c("A", "B"))

如果您只是想将个人 data.frame 提高一个级别,以便更轻松地迭代以写入文件:

unlist(exampleList, recursive=FALSE)

关于真实输出格式的假设很多(问题有点含糊)。

有一种蛮力方法可行但依赖于几个命名对象:

collectEBA <- function(x){
 df <- paste0("eba_results$",x,"$bounds")
 df <- eval(parse(text=df))[,c("type",
                            "cdf.mu.normal","cdf.above.mu.normal",
                            "cdf.mu.generic","cdf.above.mu.generic")]
 df[is.na(df)] <- "NA"
 df
 }
eba_export <- lapply(indicators,collectEBA)
names(eba_export) <- indicators