debruine / faux

R functions for simulating factorial datasets

Home Page:https://debruine.github.io/faux/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Error using rnorm_multi()

peter-hitchcock opened this issue · comments

Womp — sorry, this issue came up due to trying to use the function with a supplied matrix that wasn't positive definite; I ended up using an empirical correlation matrix and that solved it.

When I ran your code, cmat is a tibble that looks like a correlation matrix. If you want to use the full matrix specification, you need to convert this to a matrix with as.matrix().

However, it also isn't symmetric (e.g. the correlation between q_sxs_corr_1 and q_sxs_corr_2 in the upper right triangle isn't the same at the correlation between q_sxs_corr_2 and q_sxs_corr_1 in the lower left triangle).

Additionally, you're simulating correlations among the 21 items sampled from a uniform distribution between .25 and .8. That almost certainly means that the pattern of correlations you're creating will be literally impossible (i.e., not positive definite). For example, rnorm_multi(n=100, vars=3, r=c(.25, .8, -.5)) returns an error that the correlation matrix is not positive definite because if A and B correlate .25, and A and C correlate .8, then B and C can only have correlations between -0.38 and +0.78 (see faux::pos_def_limits(.25, .8, NA)).

With such a large number of intercorrelations, you need to either set all of the values to a smaller random range or use real data (which should have an achievable pattern of correlations).

I can get the following to work (also fixes the asymmetric tibble problem and reduces the questionnaire item correlation range):

GenRow <- function(iter) {
  row_without_diag <- c(
    # Questionnaire items
    runif(21, .25, .5), # reduced 0.8 to 0.5
    # Other variable
    runif(1, -.43, -.17)
  )

  row_without_diag[(iter+1):22]. # just return upper right triangle part
}

urtri <- lapply(1:21, function(x) GenRow(x)) %>% unlist()

# convert upper right triangle to full matrix
# not necessary, as the r argument will also take the URT vector, 
# but useful for checking what a symmetric matrix looks like
cmat <- faux:::cormat_from_triangle(urtri)

dat <- rnorm_multi(n=100, vars=22, r=cmat, varnames = LETTERS[1:22])

Ack, you edited while I was replying!!

Hi Lisa, Sorry about that, but that still was very useful, so thank you! I had realized the non-symmetry and generally that I'd need to put some thought into creating positive definite matrices, but that helps to see how to use pos_def_limits and cormat_from_triangle (given that it's not always desirable to use an empirical correlation matrix as I ended up doing in this case). Thank you!