1

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

rg255
  • 4,119
  • 3
  • 22
  • 40
  • Are you shying away from `sapply`/`lapply` by design? Since no parallelism is happening, this would be very appropriate. – Roman Luštrik May 12 '16 at 13:56
  • 1
    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](http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example) with sample input data so we can run it as well. – MrFlick May 12 '16 at 14:02
  • @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 May 12 '16 at 14:16
  • @mrflick will do (when back at the computer) – rg255 May 12 '16 at 14:17

1 Answers1

1

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

vasanthcullen
  • 356
  • 2
  • 9
  • 1
    I certainly would never recommend that someone use `eval(parse())`. There are almost always more R-like ways to do things. This really should only be a last resort. – MrFlick May 12 '16 at 15:19
  • It worked, thanks vasanthcullen... @Mrflick is there a specific reason one should avoid `eval(parse())`? – rg255 May 12 '16 at 20:02
  • @rg255 I'll point you to this question about the topic: http://stackoverflow.com/questions/13649979/what-specifically-are-the-dangers-of-evalparse – MrFlick May 12 '16 at 20:17