1
votes

I am using nested loops to perform multiple runs of MCMCglmm in R, outputting the posterior distributions in to data frames. The outer loop performs the MCMC process, generating posterior distributions, and then the inner loop lifts each of these in to separate data frames (where F is the number of posterior distributions in the fixed effects of each run of the chain, and n is the number of randomisations to be performed); therefore, there will be F (in this case, 4) data frames, each with n columns.

for(i in 1:n){
# Randomise
MortR = data.frame(Year, Mortalities)
MortR[,2] = sample(MortR[,2], replace = F)
DF1 = merge(DF1, MortR, by = "Year")
DF1$Mort_R = DF1[,9]
DF1[,9] = NULL

prior1 = list(G = list(  G1 = list(V = 1, nu = 1, alpha.mu = 0, alpha.V = 1000)
                        ),
                R = list(V = 1, nu = 0.002))
# Chain
assign("chainX",paste0("chain",i))
chainX =    MCMCglmm(Life ~ Sex*Mort_R - 1,
                random = ~Pop:Year,
                rcov = ~units,  
                nitt =   nitt, 
                burnin = burn, 
                thin =   thin, 
                prior = prior1, 
                pr = T,
                family = "gaussian", 
                start = list(QUASI = FALSE), 
                data = DF1)     

for(j in 1:F){
assign(paste0("chainSol",j),    chainX$Sol[,j]) 
A = as.vector(get(paste0("chainSol",j)))
assign(paste0("F",j), A)
# Aim: get vector F*j* (or A) in to column *i* of dataframe chainSolDF_*j*
# ie.: chainSolDF_*j*[,*i*] = F*j*

#chainSolDF_1[,i] = as.vector(get(paste0("chainSol",j)))   # Puts it in the columns of DF_1
#assign(paste0("chainSolDF_",j)[,i], A)                    # Incorrect number of dimensions
#assign(paste0("chainSolDF_",j)[,i], paste0("F",j))        # Error in paste0("chainSolDF_", j)[, i] : incorrect number of dimensions
#assign(paste0("chainSolDF_",j,"[,",i,"]"), paste0("F",j)) # Does not assign to the data frame
#paste0("chainSolDF_",j,"[,",i,"]") = get(paste0("F",j))   # Invalid first argument

}
#B = matrix(c(F1,F2,F3,F4), ncol = 4)
print(paste0("Randomisation ",i, " Complete"))  
}

You can see some (this is just the "highlights") of the things I've tried (#) with descriptions of the errors they generate - all to no avail! Generally I've been looking at solutions for get(), assign() and $<-. Having spent three days trying to fix this myself I'm turning to this community.

How can one assign a vector to a specific column and specific data frame, both of which are simultaneously specified within the internal nested loop?

"Aim: get vector Fj (or A) in to column i of dataframe chainSolDF_j

1
Are you shying away from sapply/lapply by design? Since no parallelism is happening, this would be very appropriate.Roman Luštrik
One rarely uses get() or assign() when programming proper R code. It's far better to collect results in named lists. This example is a bit too complex to provide a complete we-write. It would be better to simplify it (it doesn't seem to have anything to do with MCMCglmm specifically). Edit your question to isolate and simplify the problem you are really trying to solve. Also the example should be reproducible with sample input data so we can run it as well.MrFlick
@romanlustrik no reason, not got round to converting myself yet (need to take the time really) and most of what I do with loops is not computationally intense enough to make any difference time wise..rg255
@mrflick will do (when back at the computer)rg255

1 Answers

1
votes

This here is just assigning values of A into column i of dataframe chainSolDF_j by using the same two for loops

# creating mock data for the dataframes
chainSolDF_1 <- data.frame(col1 = 1:10, col2 = 1:10, col3 = 1:10)
chainSolDF_2 <- data.frame(col1 = 1:10, col2 = 1:10, col3 = 1:10)
chainSolDF_3 <- data.frame(col1 = 1:10, col2 = 1:10, col3 = 1:10)

# assigning values of A into column i of dataframe chainSolDF_j
for (i in 1:3) {
  for (j in 1:3) {
    # creating mock data for A
    A <- 0L
    eval(expr = parse(text = paste0("chainSolDF_", j, "[, ", i, "] <- A")))
  }
}

Edit : To be more related to the question, use

eval(expr = parse(text = paste0("chainSolDF_", j, "[, ", i, "] <- A")))

in the j for loop, like

for(j in 1:F){
  assign(paste0("chainSol",j),    chainX$Sol[,j]) 
  A = as.vector(get(paste0("chainSol",j)))
  eval(expr = parse(text = paste0("chainSolDF_", j, "[, ", i, "] <- A")))
}

Let me know if it helps