将列表更有效地组合到数据帧中

时间:2018-02-18 21:40:04

标签: r apply lapply mcmc mapply

我正在运行MCMCglmm()模型的多个链,我正在尝试找到合成输出的最有效方法。

我使用mclapply()运行4个链,然后将4个链中的每个链组合成一个lapply()的列表。

这是我清理和组合链的模型和代码。我正在使用这个有用的教程来运行链:https://github.com/tmalsburg/MCMCglmm-intro

型号:

library(parallel)
chains <- mclapply(1:4, function(i) {
  MCMCglmm(outcome ~ 1 + pretest + race + satisfaction*race, data = data,
                                random = ~ provider,
                                prior = prior.1,
                                verbose = TRUE,
                                family = "gaussian",
                                nitt = 10000, 
                                burnin = 5000, 
                                thin = 10)
}, mc.cores=4)

我的清理有点笨重。有没有办法在固定和随机效果上运行lapply命令(或者我认为需要mapply)将它们组合到同一个列表和后续数据框中?最后,我希望有一个数据框,以便我可以添加/减去后验分布并对它们运行汇总统计。

fixed <- lapply(chains, function(m) m$Sol) # Sol = fixed effects 
fixed <- do.call(mcmc.list, fixed)
summary(fixed)

random <- lapply(chains, function(m) m$VCV) # VCV = variance 
random <- do.call(mcmc.list, random)
summary(random)

fixed_df <- do.call(rbind, Map(data.frame, fixed))
random_df <- do.call(rbind, Map(data.frame, random))

chains_df <- cbind(fixed_df, random_df)

最终,我希望运行一个lapply()mapply()并拥有一个fixed.random列表。我相信我可以使用Map(data.frame, fixed.random)来创建我的数据框。我对apply函数的了解是有限的,所以我希望学习更多知识并将其应用到我的数据集中(没有双关语)。

不幸的是,模型输出了MCMC对象,因此我无法创建确切的结构。这是我能想到的最好的:

list1 <- list(a = rnorm(100, 0, 1), b = rnorm(100, 0, 1))
list2 <- list(a = rnorm(100, 0, 1), b = rnorm(100, 0, 1))
list3 <- list(a = rnorm(100, 0, 1), b = rnorm(100, 0, 1))
list4 <- list(a = rnorm(100, 0, 1), b = rnorm(100, 0, 1))

list5 <- list(d = rnorm(100, 0, 1), e = rnorm(100, 0, 1))
list6 <- list(d = rnorm(100, 0, 1), e = rnorm(100, 0, 1))
list7 <- list(d = rnorm(100, 0, 1), e = rnorm(100, 0, 1))
list8 <- list(d = rnorm(100, 0, 1), e = rnorm(100, 0, 1))

fixed  <- list(list1, list2, list3, list4)
random <- list(list5, list6, list7, list8)

1 个答案:

答案 0 :(得分:1)

以下是否会这样做?

假设您的four_mcmc是班级"MCMCglmm"chain1chain2等)的模型列表,extract是元素列表你想从链中读取(在你的情况下是固定的("Sol")和随机的术语("VCV"))。

## The list of mcmcs
four_mcmc <- list(chain1, chain2, chain3, chain4)

## Which elements to extract from the MCMCs
extract <- c("VCV", "Sol")

您可以使用get.element函数从单个链中提取单个元素列表:

## Extracting some specific elements from a chain
get.elements <- function(extract, mcmc) {
    ## Extracting the element
    mcmc_elements <- sapply(extract, function(extract) mcmc[which(names(mcmc) == extract)])
}

## Extracting the VCV and Sol from one chain
str(get.elements(extract, chain1))

然后,您只需将此功能应用于您的链列表:

## Applying get.element for each elements to extract on each chain
all_elements <- lapply(four_mcmc, function(mcmc, extract) get.elements(extract, mcmc), extract)

然后,您可以轻松地将此表格作为数据框汇总为每个术语,其中术语为行,链为列

## Fixed terms table
fixed_terms <- as.data.frame(lapply(all_elements, function(X) X[[1]]))
## Random terms table
random_terms <- as.data.frame(lapply(all_elements, function(X) X[[2]]))

此代码来自https://github.com/TGuillerme/mulTreeread.mulTree函数。

[编辑] @headpoint建议只使用:

as.data.frame(lapply(chains, function(m) cbind(m$Sol, m$VCV)))

哪个更优雅,但可移动性更低。