Search code examples
rfor-loopnested-loops

Replace nested loops that iterates over a function - R


I have a nested loop that iterates over a function, but I want to avoid running the nested loop. However, I'm stuck on the implementation of an alternative script that will run and save the output.

Below is the loop, and other useful information to run the complete script.

# data
df = data.frame(y1 = sample(x=0L:1L, size=120, replace=TRUE),
                y2 = sample(x=0L:1L, size=120, replace=TRUE),
                x1 = sample(x=1L:3L, size=120, replace=TRUE),
                x2 = sample(x=1L:3L, size=120, replace=TRUE),
                x3 = sample(x=1L:3L, size=120, replace=TRUE),
                wgt = sample(runif(120, min=.25, max=.70), replace=TRUE))

#the function
chi2_test <- function(...){
  termlabels = sapply(substitute(...()), deparse)
  form <- reformulate(termlabels=termlabels, response="wgt")
  
  cross_table = xtabs(form, data=df)
  chi2_test = chisq.test(cross_table, correct=TRUE)

  return(list(crosstabs = cross_table,
              chi2_test = chi2_test)
  )
}

# dvs and ivs
dvars = names(df)[1:2]
ivars = names(df)[3:5]
combos = tidyr::crossing(dvars, ivars)

# the loop: where I need some help with
for (i in combos$dvars){
  for (j in combos$ivars){
    cat(i, "by", j)
    print(chi2_test(df[, i], df[, j]))
  }
}

Solution

  • The nested loop is not needed as the full combination was already created with crossing. So, just loop over the sequence of rows of combos, extract the names corresponding to each row, subset the df column based on that and assign the output to an initialized list of the same length as number of roww of combos

    out <- vector('list', nrow(combos))
    names(out) <- do.call(paste, c(combos, sep = " by "))
    for(i in seq_along(combos$dvars)) 
      out[[i]] <- chi2_test(df[, combos$dvars[i]], df[, combos$ivars[i]])
    

    -output

    > out[1]
    $`y1 by x1`
    $`y1 by x1`$crosstabs
                         df[, combos$ivars[i]]
    df[, combos$dvars[i]]         1         2         3
                        0 10.926195  8.558175  6.373337
                        1 13.388605  8.971302  8.481009
    
    $`y1 by x1`$chi2_test
    
        Pearson's Chi-squared test
    
    data:  cross_table
    X-squared = 0.12113, df = 2, p-value = 0.9412