Home > Back-end >  Nested for loop: problem with indexing in R
Nested for loop: problem with indexing in R

Time:07-06

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?

CodePudding user response:

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"        
  • Related