Search code examples
rfor-loopindexingnested-loops

Nested for loop: problem with indexing in R


I'm struggling to get the correct index in nested for-loops in R.

Here's an example:

# First: create function that inserts character pattern in string
  fun_insert <- function(x, pos, insert) {
    gsub(paste0("^(.{", pos, "})(.*)$"),
         paste0("\\1", insert, "\\2"),
         x)
  }

# Variables:
original_m<-c("BODYSHAME", "WBIS_M")
k<-length(original_m)
storage_mod_xm_all<-c("FEAROFSELFCOMPASSION", "SBOSS")
nmod_xm_all<-length(storage_mod_xm_all)
storage_med_pt1<-c("BODYSHAME ~ a1*","WBIS_M ~ a2*")
storage_mod_xm<-0

Now I want to use nested for-loops to get this output in the variable storage_mod_xm (a list with the following character strings):

"BODYSHAME ~ a11*FEARSELFCOMPASSION" "WBIS_M ~ a21*FEARSELFCOMPASSION"    "BODYSHAME ~ a12*SOBBS"             
"WBIS_M ~ a22*SOBBS"

So basically the first index after a should refer to the number of element from the variable original_m and the second index should refer to the number of element from the variable storage_mod_xm_all.

How I tried to do this:

# --> M ~ a*W

if (nmod_xm_all>0){
# combine M ~ b* and x-m moderator
  storage_mod_xm_pt1<-outer(storage_med_pt1, storage_mod_xm_all, FUN = "paste0") 
  dim(storage_mod_xm_pt1)<-NULL
  n_st_mod_xm<-length(storage_mod_xm_pt1)
  # for loop over all mediators
  for (j in 1:k) {
    # for loop over all moderators
    for (i in 1:n_st_mod_xm){
      storage_mod_xm_pt2[i]<-fun_insert(storage_mod_xm_pt1[i], pos=(nchar(original_m[j])+5), insert=i) # insert different index to label
    } # end of for loop moderators
  } # end of for loop mediators
  storage_mod_xm<-paste(c(storage_mod_xm_pt2), collapse=";") #""M1 ~ a11*gender_M;M2 ~ a22*gender_M"
} # end of if-else statement 

The output I get from the variable storage_mod_xm:

"BODYSHAME ~1 a1*FEARSELFCOMPASSION" "WBIS_M ~ a22*FEARSELFCOMPASSION"    "BODYSHAME ~3 a1*SOBBS"             
[4] "WBIS_M ~ a24*SOBBS"

BUT desired output:

"BODYSHAME ~ a11*FEARSELFCOMPASSION" "WBIS_M ~ a21*FEARSELFCOMPASSION"    "BODYSHAME ~ a12*SOBBS"             
[4] "WBIS_M ~ a22*SOBBS"

Anyone a solution how to fix this?


Solution

  • I have a slightly different solution -

    • Simplified fun_insert function to a one-liner sprintf.
    • Added an additional argument in fun_insert (j) so that we can get rid of storage_med_pt1.
    • Instead of nested for loop I have used nested sapply. It works the same way.
    fun_insert <- function(org, i, j, stor) sprintf('%s ~ a%i%i*%s', org, i, j, stor)
    
    #For one value
    fun_insert(original_m[1], 1, 1, storage_mod_xm_all[1])
    #[1] "BODYSHAME ~ a11*FEAROFSELFCOMPASSION"
    
    #For all of them
    c(t(sapply(seq_along(original_m), function(x) {
      sapply(seq_along(storage_mod_xm_all), function(y) {
        fun_insert(original_m[x], x, y, storage_mod_xm_all[y])
      })
    })))
    
    #[1] "BODYSHAME ~ a11*FEAROFSELFCOMPASSION" "WBIS_M ~ a21*FEAROFSELFCOMPASSION" 
    #[3] "BODYSHAME ~ a12*SBOSS"                "WBIS_M ~ a22*SBOSS"