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-linersprintf
. - Added an additional argument in
fun_insert
(j
) so that we can get rid ofstorage_med_pt1
. - Instead of nested
for
loop I have used nestedsapply
. 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"