# How to generate correlated nominal variables?

I have 15 nominal variables (unordered), and all of them have more than 2 categories. I used Cramer's V to get a correlation matrix. Now I want to create correlated nominal variables by the marginal distributions and correlation matrix. Most answers I viewed are based on Pearson correlation, or using copula method assuming normal or other distributions. But Pearson coefficient can't be used here since all the variables are nominal, and I don't think I could use the normal distribution assumption. Is there a more general solution?

• This qiestion: stats.stackexchange.com/q/128899/3277 asks about specifically ordinal variables while you ask about nominal. However, you might find it relevant as well. – ttnphns Feb 7 '17 at 11:32
• One possible idea is to use iterative proportional fitting - the algorithm that is used in the form of multivariate re-weighting of categorical data called rim or raking weighting as well as in loglinear analysis. In the rim weighting, we train magrinal frequencies iteratively towards the wanted ones. Now, the (raw) present idea is to train the marginal frequencies towards target bivariate association (such as Cramer or chi-sq) instead. I haven't tried/done it myself, though. So I'm not sure. – ttnphns Feb 7 '17 at 11:42

I don't know how you would use Cramer's $V$ to do this. I assume there is some fancy way to generate such data, but I don't know it. What I can do is give you a simple fall-back method.

If you can stipulate the joint probability of every combination of levels of your categorical variables (i.e., the probability an observation will fall into the combination of level $i$ of variable 1, level $j$ of variable 2, level $k$ of variable 3, etc., for all levels of all variables), you can simply draw random variates from a standard uniform and compare that value to the ordered set of probabilities to determine which cell it should be in. Note that if you want to individually create these by hand, it could take you a while: e.g., with fifteen variables with three levels each, that's $3^{15} = 14,\!348,\!907$ individual probabilities that would need to be specified! If you have a dataset whose proportions you want to serve as a template for the probabilities, you can write simple code to do this for you. Either way, that does amount to having specified the correlational structure of the population exactly.

To demonstrate this, consider a simpler situation with just two categorical variables with three levels each. Here I create a simple simulation (coded in R):

##### Here are the joint probabilities I want to use:
#    y
# x      A    B    C
#   a 0.13 0.18 0.11
#   b 0.02 0.11 0.11
#   c 0.18 0.05 0.11
##### here they are in a single row vector:
probs     = c(0.13, 0.18, 0.11, 0.02, 0.11, 0.11, 0.18, 0.05, 0.11)
cum.probs = c(0, cumsum(probs))  # notice I put a 0 at the beginning
cum.probs
# [1] 0.00 0.13 0.31 0.42 0.44 0.55 0.66 0.84 0.89 1.00

set.seed(8982)                # this makes the example exactly reproducible
vals = runif(500)             # generate 500 random values / probabilities
##### cut the random uniform values into cell categories:
cats = cut(vals, breaks=cum.probs,
labels=c("aA","aB","aC","bA","bB","bC", "cA", "cB", "cC"))
low  = substr(cats, start=1, stop=1)  # extract the 1st letter
up   = substr(cats, start=2, stop=2)  # extract the 2nd letter
##### these are the observed counts:
table(low, up)
#    up
# low  A  B  C
#   a 68 98 54
#   b  7 47 67
#   c 77 25 57
##### this is a reasonable match to the population pattern specified:
prop.table(table(low, up))
#    up
# low     A     B     C
#   a 0.136 0.196 0.108
#   b 0.014 0.094 0.134
#   c 0.154 0.050 0.114


Now, what if you had data, and you wanted to use those proportions instead of specifying 14+ million combinations by hand? Then you just get the proportions from your dataset and put them into a single vector. For example, like so:

props = as.vector(t(prop.table(table(low, up))))
props
# [1] 0.136 0.196 0.108 0.014 0.094 0.134 0.154 0.050 0.114

• The answer is awesome, thanks. But my actual case is..there are 25 variables and 611,529,523,200 cells to specify...which exceeds R's maximum vector length 2^31-1...I am thinking maybe I could cut variables into several parts and then try your method separately... – qianw Mar 24 '17 at 14:28
• Presumably, @qianw. I bet there is also an existing R method for that kind of problem. You could ask about that as a pure programming question on Stack Overflow, if you wanted. – gung Mar 24 '17 at 14:52