<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Question on Simulating Correlated Ordinal Data with Random effect in SAS Procedures</title>
    <link>https://communities.sas.com/t5/SAS-Procedures/Question-on-Simulating-Correlated-Ordinal-Data-with-Random/m-p/193213#M48505</link>
    <description>&lt;HTML&gt;&lt;HEAD&gt;&lt;/HEAD&gt;&lt;BODY&gt;&lt;P&gt;&lt;SPAN style="font-size: 14pt;"&gt;&lt;STRONG&gt;Hi all,&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 14pt;"&gt;&lt;STRONG&gt;Recently I was working on a project to perform a Simulation on Correlated Ordinal Data with Random effect. I need to generate two groups of ordinal variables which were correlated with each other, &lt;SPAN style="line-height: 1.5em;"&gt;and each pair of values should come from one subject which is a random effect.&lt;/SPAN&gt;&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 14pt;"&gt;&lt;STRONG&gt;&lt;SPAN style="line-height: 1.5em;"&gt; According to &lt;/SPAN&gt;&lt;A class="active_link" href="http://blogs.sas.com/content/iml/author/rickwicklin/" style="line-height: 1.5em; font-size: 16px; color: #628cb2; font-family: Arial, sans-serif; font-weight: bold; background-position: initial;"&gt;Rick Wicklin&lt;/A&gt;&lt;SPAN style="line-height: 1.5em;"&gt;'s book,&lt;/SPAN&gt;&lt;A href="http://www.sas.com/storefront/aux/en/spsimulationofdata/65378_excerpt.pdf" style="font-family: arial, sans-serif; font-size: 18px; line-height: 1.5em; color: #660099;"&gt;Simulating Data with SAS&lt;/A&gt;&lt;SPAN style="line-height: 1.5em;"&gt;, &lt;/SPAN&gt;&lt;SPAN style="line-height: 1.5em;"&gt;I used the &lt;/SPAN&gt;&lt;SPAN style="line-height: 1.5em;"&gt;method in chapter 9.3.2 to create correlated ordinal variables, but not sure how to add in random effect into the proc iml functions (especially the RandMVOrdinal function).&lt;/SPAN&gt;&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 14pt;"&gt;&lt;STRONG&gt;You could find the original code on Rick's blog.&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;/*code in Chapter 9.3.2*/&lt;/P&gt;&lt;P&gt;/***********************************************************************&lt;/P&gt;&lt;P&gt; Programs for &lt;/P&gt;&lt;P&gt; Wicklin, Rick, 2013, Simulating Data with SAS, SAS Institute Inc., Cary NC.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt; Appendix B: Generating Multivariate Ordinal Variables&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt; This program saves functions to the SAS/IML storage library.&lt;/P&gt;&lt;P&gt; To use these functions in a SAS/IML program, run this program&lt;/P&gt;&lt;P&gt; and then load the functions, as follows:&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt; ***********************************************************************/&lt;/P&gt;&lt;P&gt;proc iml;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* P1&amp;nbsp;&amp;nbsp; P2&amp;nbsp;&amp;nbsp;&amp;nbsp; P3&amp;nbsp; */&lt;/P&gt;&lt;P&gt;/* example matrix of PMFs */&lt;/P&gt;&lt;P&gt;/*&lt;/P&gt;&lt;P&gt;P = {0.25&amp;nbsp; 0.50&amp;nbsp; 0.20 ,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0.75&amp;nbsp; 0.20&amp;nbsp; 0.15 ,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .&amp;nbsp;&amp;nbsp;&amp;nbsp; 0.30&amp;nbsp; 0.25 ,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .&amp;nbsp;&amp;nbsp;&amp;nbsp; 0.40 };&lt;/P&gt;&lt;P&gt;*/&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;/* OrdN: number of values for each variable */&lt;/P&gt;&lt;P&gt;start OrdN(P);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; return( countn(P, "col") );&lt;/P&gt;&lt;P&gt;finish;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;/* OrdMean: Expected value for each variable is Sigma_i (i*p&lt;I&gt;)&amp;nbsp;&amp;nbsp;&amp;nbsp; */&lt;/I&gt;&lt;/P&gt;&lt;P&gt;start OrdMean(P);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; x = T(1:nrow(P));&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* values of ordinal vars&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; */&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; return( (x#P)[+,] );&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* expected values E(X)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; */&lt;/P&gt;&lt;P&gt;finish;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;/* OrdVar: variance for each variable */&lt;/P&gt;&lt;P&gt;start OrdVar(P);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; d = ncol(P);&amp;nbsp;&amp;nbsp; m = OrdMean(P);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; x = T(1:nrow(P));&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* values of ordinal vars&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; */&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; var = j(1, d, 0);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; do i = 1 to d;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var&lt;I&gt; = sum( (x - m&lt;I&gt;)##2 # P[,i] );&amp;nbsp;&amp;nbsp;&amp;nbsp; /* defn of variance */&lt;/I&gt;&lt;/I&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; end;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; return( var );&lt;/P&gt;&lt;P&gt;finish;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;/* OrdCDF: Given PMF, compute CDF = cusum(PDF) */&lt;/P&gt;&lt;P&gt;start OrdCDF(P);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; cdf = j(nrow(P), ncol(P));&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* cumulative probabilities&amp;nbsp;&amp;nbsp;&amp;nbsp; */&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; do i = 1 to ncol(P);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cdf[,i] = cusum(P[,i]);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; end;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; return( choose(P=., ., cdf) );&amp;nbsp;&amp;nbsp;&amp;nbsp; /* missing vals for short cols */&lt;/P&gt;&lt;P&gt;finish;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;/* Function that returns ordered pairs on a uniform grid of points.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; Return value is an (Nx*Ny x 2) matrix */&lt;/P&gt;&lt;P&gt;start Expand2DGrid( _x, _y );&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; x&amp;nbsp; = colvec(_x); y&amp;nbsp; = colvec(_y);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; Nx = nrow(x);&amp;nbsp;&amp;nbsp;&amp;nbsp; Ny = nrow(y);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; x = repeat(x, Ny);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; y = shape( repeat(y, 1, Nx), 0, 1 );&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; return ( x || y );&lt;/P&gt;&lt;P&gt;finish;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;/* OrdQuant: Compute normal quantiles for CDF(P) */&lt;/P&gt;&lt;P&gt;start OrdQuant(P);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; N = OrdN(P);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; CDF = OrdCDF(P);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; /* QUANTILE function in SAS/IML 12.1 does not accept 1 as parameter */&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; /* Replace 1 with missing value to prevent error */&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; CDF = choose(CDF &amp;gt; 1 - 2e-6, ., CDF);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; quant = quantile( "Normal", cdf );&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; do j = 1 to ncol(P);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* set upper quantile to .I = infinity */&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; quant[N&lt;J&gt;,j] = .I;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* .I has special meaning to BIN func&amp;nbsp; */&lt;/J&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; end;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; return( quant );&lt;/P&gt;&lt;P&gt;finish;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;/* OrdFindRoot: Use bisection to find the MV normal correlation that &lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; produces a specified MV ordinal correlation. */&lt;/P&gt;&lt;P&gt;start OrdFindRoot(P1, P2,&amp;nbsp; target);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; N1 = countn(P1);&amp;nbsp;&amp;nbsp; N2 = countn(P2);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; q1 = OrdQuant(P1); q2 = OrdQuant(P2);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; v1 = q1[1:N1-1];&amp;nbsp;&amp;nbsp; v2 = q2[1:N2-1];&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; g = Expand2DGrid(v1, v2);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; /* find value of rho so that sum(probbnrm(g[,1], g[,2], rho))=target */&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; /* Bisection: find root on bracketing interval [a,b] */&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; a = -1; b = 1;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* look for correlation in [-1,1] */&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; dx = 1e-8; dy = 1e-5;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; do i = 1 to 100;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* iterate until convergence&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; */&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; c = (a+b)/2;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Fc = sum( probbnrm(g[,1], g[,2], c) ) - target;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (abs(Fc) &amp;lt; dy) | (b-a)/2 &amp;lt; dx then &lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return(c);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Fa = sum( probbnrm(g[,1], g[,2], a) ) - target;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if Fa#Fc &amp;gt; 0 then a = c;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else b = c;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; end;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; return (.);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* no convergence&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; */&lt;/P&gt;&lt;P&gt;finish;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;/* alternative root-finding algorithm that uses FROOT (SAS 12.1) */&lt;/P&gt;&lt;P&gt;/*&lt;/P&gt;&lt;P&gt;start MMRoot(x) global(_grid, _target);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; return( sum( probbnrm(_grid[,1], _grid[,2], x) ) - _target );&lt;/P&gt;&lt;P&gt;finish;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;start AltOrdFindRoot(P1, P2,&amp;nbsp; target) global(_grid, _target);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; N1 = countn(P1);&amp;nbsp;&amp;nbsp; N2 = countn(P2);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; q1 = OrdQuant(P1); q2 = OrdQuant(P2);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; v1 = q1[1:N1-1];&amp;nbsp;&amp;nbsp; v2 = q2[1:N2-1];&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; _grid = Expand2DGrid(v1, v2);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; _target = target;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; return( froot("MMRoot", {-1 1}) );&lt;/P&gt;&lt;P&gt;finish;&lt;/P&gt;&lt;P&gt;*/&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;/* OrdMVCorr: Compute a MVN correlation matrix from the PMF and &lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; the target correlation matrix for the ordinal variables. */&lt;/P&gt;&lt;P&gt;start OrdMVCorr(P, Corr);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; d = ncol(P);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; N = OrdN(P);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; mean = OrdMean(P);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; var&amp;nbsp; = OrdVar(P);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; cdf&amp;nbsp; = OrdCDF(P);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; R = I(d);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; do i = 1 to d-1;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sumCDFi = sum(cdf[1:N&lt;I&gt;-1, i]); &lt;/I&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; do j = i+1 to d;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sumCDFj = sum(cdf[1:N&lt;J&gt;-1, j]); &lt;/J&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; hStar = Corr[i,j] * sqrt(var&lt;I&gt;*var&lt;J&gt;) + mean&lt;I&gt;*mean&lt;J&gt; &lt;/J&gt;&lt;/I&gt;&lt;/J&gt;&lt;/I&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; - N&lt;I&gt;*N&lt;J&gt; + N&lt;I&gt;*sumCDFj + N&lt;J&gt;*sumCDFi;&lt;/J&gt;&lt;/I&gt;&lt;/J&gt;&lt;/I&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; R[i,j] = OrdFindRoot(P[,i], P[,j], hStar);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; R[j,i] = R[i,j];&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; end;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; end;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; return(R);&lt;/P&gt;&lt;P&gt;finish;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;/* RandMVOrdinal: &lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; N&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Number of desired observations from MV ordinal distribution, &lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; P&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Matrix of PMF for ordinal vars. The j_th col is the j_th PMF.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Use missing vals if some vars have fewer values than others.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; Corr&amp;nbsp; Desired correlation matrix for ordinal variables. Not every&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; matrix is a valid as the correlation of ordinal variables. */&lt;/P&gt;&lt;P&gt;start RandMVOrdinal(N, P, Corr);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; d = ncol(P);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; C = OrdMVCorr(P, Corr);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* 1. compute correlation matrix, C&amp;nbsp; */&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; mu = j(1, d, 0);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; X = RandNormal(N, mu, C);&amp;nbsp;&amp;nbsp; /* 2. simulate X ~ MVN(0,C)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; */&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; N = OrdN(P);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; quant = OrdQuant(P);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* compute normal quantiles for PMFs */&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; do j = 1 to d;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* 3. convert to ordinal&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; */&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; X[,j] = bin(X[,j], .M // quant[1:N&lt;J&gt;,j]);&lt;/J&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; end;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; return(X);&lt;/P&gt;&lt;P&gt;finish;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;store module=_all_;&lt;/P&gt;&lt;P&gt;quit;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;proc iml;&lt;/P&gt;&lt;P&gt;load module=_all_;&lt;/P&gt;&lt;P&gt;p={0.16 0.16,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; 0.28 0.28,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; 0.2&amp;nbsp; 0.2 ,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; 0.15 0.15,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; 0.12 0.12,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; 0.06 0.06,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; 0.03 0.03 };&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;delta={1.0 0.5,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0.5 1.0};&lt;/P&gt;&lt;P&gt;call randseed(1234);&lt;/P&gt;&lt;P&gt;x=RandMVOrdinal(60,p,delta);&lt;/P&gt;&lt;P&gt;create mn from x;append from x; close mn;&lt;/P&gt;&lt;P&gt; *****************************************************************************************************************************************;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 14pt;"&gt;&lt;STRONG&gt;Chapter 12.3.1 provided an example of adding random effect for a continuous variable. I am not sure if I could just use the same method. Do you guys have any code already for Ordinal Variables? If not, could you please provide any guidance on this? How would you control the random components?&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt; *****************************************************************************************************************************************;&lt;/P&gt;&lt;P&gt;/*code in Chapter 12.3.1*/&lt;/P&gt;&lt;P&gt;/*simple random effect model with repeated measurements*/&lt;/P&gt;&lt;P&gt;%let var_A=4;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /*variance of random effect (intercept)&amp;nbsp; */&lt;/P&gt;&lt;P&gt;%let sigma2=2;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /*variance of residual, N(0, sqrt(sigma2))&amp;nbsp; */&lt;/P&gt;&lt;P&gt;%let L=3;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /*num levels in random effect A*/&lt;/P&gt;&lt;P&gt;%let K=5;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /*num repeated measurements in each level of A */&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;data randomeffects(12345);&lt;/P&gt;&lt;P&gt;call streaminit(12345);&lt;/P&gt;&lt;P&gt;mu=5;&lt;/P&gt;&lt;P&gt;do a=1 to &amp;amp;L;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; rndA=rand("Normal", 0, sqrt(&amp;amp;var_A));&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; do rep=1 to &amp;amp;k;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; y= mu +rndA+rand("Normal", 0, sqrt(&amp;amp;sigma2));&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; output;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; end;&lt;/P&gt;&lt;P&gt;end;&lt;/P&gt;&lt;P&gt;run;&lt;/P&gt;&lt;P&gt; *****************************************************************************************************************************************;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 14pt;"&gt;&lt;STRONG style="color: #575757;"&gt;Look forward to your guidance,&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 14pt;"&gt;&lt;STRONG style="color: #575757;"&gt;Thanks,&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 14pt;"&gt;&lt;STRONG style="color: #575757;"&gt;Fred&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/BODY&gt;&lt;/HTML&gt;</description>
    <pubDate>Fri, 10 Apr 2015 15:13:02 GMT</pubDate>
    <dc:creator>FredXu</dc:creator>
    <dc:date>2015-04-10T15:13:02Z</dc:date>
    <item>
      <title>Question on Simulating Correlated Ordinal Data with Random effect</title>
      <link>https://communities.sas.com/t5/SAS-Procedures/Question-on-Simulating-Correlated-Ordinal-Data-with-Random/m-p/193213#M48505</link>
      <description>&lt;HTML&gt;&lt;HEAD&gt;&lt;/HEAD&gt;&lt;BODY&gt;&lt;P&gt;&lt;SPAN style="font-size: 14pt;"&gt;&lt;STRONG&gt;Hi all,&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 14pt;"&gt;&lt;STRONG&gt;Recently I was working on a project to perform a Simulation on Correlated Ordinal Data with Random effect. I need to generate two groups of ordinal variables which were correlated with each other, &lt;SPAN style="line-height: 1.5em;"&gt;and each pair of values should come from one subject which is a random effect.&lt;/SPAN&gt;&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 14pt;"&gt;&lt;STRONG&gt;&lt;SPAN style="line-height: 1.5em;"&gt; According to &lt;/SPAN&gt;&lt;A class="active_link" href="http://blogs.sas.com/content/iml/author/rickwicklin/" style="line-height: 1.5em; font-size: 16px; color: #628cb2; font-family: Arial, sans-serif; font-weight: bold; background-position: initial;"&gt;Rick Wicklin&lt;/A&gt;&lt;SPAN style="line-height: 1.5em;"&gt;'s book,&lt;/SPAN&gt;&lt;A href="http://www.sas.com/storefront/aux/en/spsimulationofdata/65378_excerpt.pdf" style="font-family: arial, sans-serif; font-size: 18px; line-height: 1.5em; color: #660099;"&gt;Simulating Data with SAS&lt;/A&gt;&lt;SPAN style="line-height: 1.5em;"&gt;, &lt;/SPAN&gt;&lt;SPAN style="line-height: 1.5em;"&gt;I used the &lt;/SPAN&gt;&lt;SPAN style="line-height: 1.5em;"&gt;method in chapter 9.3.2 to create correlated ordinal variables, but not sure how to add in random effect into the proc iml functions (especially the RandMVOrdinal function).&lt;/SPAN&gt;&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 14pt;"&gt;&lt;STRONG&gt;You could find the original code on Rick's blog.&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;/*code in Chapter 9.3.2*/&lt;/P&gt;&lt;P&gt;/***********************************************************************&lt;/P&gt;&lt;P&gt; Programs for &lt;/P&gt;&lt;P&gt; Wicklin, Rick, 2013, Simulating Data with SAS, SAS Institute Inc., Cary NC.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt; Appendix B: Generating Multivariate Ordinal Variables&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt; This program saves functions to the SAS/IML storage library.&lt;/P&gt;&lt;P&gt; To use these functions in a SAS/IML program, run this program&lt;/P&gt;&lt;P&gt; and then load the functions, as follows:&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt; ***********************************************************************/&lt;/P&gt;&lt;P&gt;proc iml;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* P1&amp;nbsp;&amp;nbsp; P2&amp;nbsp;&amp;nbsp;&amp;nbsp; P3&amp;nbsp; */&lt;/P&gt;&lt;P&gt;/* example matrix of PMFs */&lt;/P&gt;&lt;P&gt;/*&lt;/P&gt;&lt;P&gt;P = {0.25&amp;nbsp; 0.50&amp;nbsp; 0.20 ,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0.75&amp;nbsp; 0.20&amp;nbsp; 0.15 ,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .&amp;nbsp;&amp;nbsp;&amp;nbsp; 0.30&amp;nbsp; 0.25 ,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .&amp;nbsp;&amp;nbsp;&amp;nbsp; 0.40 };&lt;/P&gt;&lt;P&gt;*/&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;/* OrdN: number of values for each variable */&lt;/P&gt;&lt;P&gt;start OrdN(P);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; return( countn(P, "col") );&lt;/P&gt;&lt;P&gt;finish;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;/* OrdMean: Expected value for each variable is Sigma_i (i*p&lt;I&gt;)&amp;nbsp;&amp;nbsp;&amp;nbsp; */&lt;/I&gt;&lt;/P&gt;&lt;P&gt;start OrdMean(P);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; x = T(1:nrow(P));&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* values of ordinal vars&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; */&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; return( (x#P)[+,] );&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* expected values E(X)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; */&lt;/P&gt;&lt;P&gt;finish;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;/* OrdVar: variance for each variable */&lt;/P&gt;&lt;P&gt;start OrdVar(P);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; d = ncol(P);&amp;nbsp;&amp;nbsp; m = OrdMean(P);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; x = T(1:nrow(P));&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* values of ordinal vars&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; */&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; var = j(1, d, 0);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; do i = 1 to d;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var&lt;I&gt; = sum( (x - m&lt;I&gt;)##2 # P[,i] );&amp;nbsp;&amp;nbsp;&amp;nbsp; /* defn of variance */&lt;/I&gt;&lt;/I&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; end;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; return( var );&lt;/P&gt;&lt;P&gt;finish;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;/* OrdCDF: Given PMF, compute CDF = cusum(PDF) */&lt;/P&gt;&lt;P&gt;start OrdCDF(P);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; cdf = j(nrow(P), ncol(P));&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* cumulative probabilities&amp;nbsp;&amp;nbsp;&amp;nbsp; */&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; do i = 1 to ncol(P);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cdf[,i] = cusum(P[,i]);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; end;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; return( choose(P=., ., cdf) );&amp;nbsp;&amp;nbsp;&amp;nbsp; /* missing vals for short cols */&lt;/P&gt;&lt;P&gt;finish;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;/* Function that returns ordered pairs on a uniform grid of points.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; Return value is an (Nx*Ny x 2) matrix */&lt;/P&gt;&lt;P&gt;start Expand2DGrid( _x, _y );&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; x&amp;nbsp; = colvec(_x); y&amp;nbsp; = colvec(_y);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; Nx = nrow(x);&amp;nbsp;&amp;nbsp;&amp;nbsp; Ny = nrow(y);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; x = repeat(x, Ny);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; y = shape( repeat(y, 1, Nx), 0, 1 );&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; return ( x || y );&lt;/P&gt;&lt;P&gt;finish;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;/* OrdQuant: Compute normal quantiles for CDF(P) */&lt;/P&gt;&lt;P&gt;start OrdQuant(P);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; N = OrdN(P);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; CDF = OrdCDF(P);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; /* QUANTILE function in SAS/IML 12.1 does not accept 1 as parameter */&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; /* Replace 1 with missing value to prevent error */&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; CDF = choose(CDF &amp;gt; 1 - 2e-6, ., CDF);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; quant = quantile( "Normal", cdf );&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; do j = 1 to ncol(P);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* set upper quantile to .I = infinity */&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; quant[N&lt;J&gt;,j] = .I;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* .I has special meaning to BIN func&amp;nbsp; */&lt;/J&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; end;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; return( quant );&lt;/P&gt;&lt;P&gt;finish;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;/* OrdFindRoot: Use bisection to find the MV normal correlation that &lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; produces a specified MV ordinal correlation. */&lt;/P&gt;&lt;P&gt;start OrdFindRoot(P1, P2,&amp;nbsp; target);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; N1 = countn(P1);&amp;nbsp;&amp;nbsp; N2 = countn(P2);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; q1 = OrdQuant(P1); q2 = OrdQuant(P2);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; v1 = q1[1:N1-1];&amp;nbsp;&amp;nbsp; v2 = q2[1:N2-1];&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; g = Expand2DGrid(v1, v2);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; /* find value of rho so that sum(probbnrm(g[,1], g[,2], rho))=target */&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; /* Bisection: find root on bracketing interval [a,b] */&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; a = -1; b = 1;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* look for correlation in [-1,1] */&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; dx = 1e-8; dy = 1e-5;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; do i = 1 to 100;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* iterate until convergence&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; */&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; c = (a+b)/2;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Fc = sum( probbnrm(g[,1], g[,2], c) ) - target;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (abs(Fc) &amp;lt; dy) | (b-a)/2 &amp;lt; dx then &lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return(c);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Fa = sum( probbnrm(g[,1], g[,2], a) ) - target;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if Fa#Fc &amp;gt; 0 then a = c;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else b = c;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; end;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; return (.);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* no convergence&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; */&lt;/P&gt;&lt;P&gt;finish;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;/* alternative root-finding algorithm that uses FROOT (SAS 12.1) */&lt;/P&gt;&lt;P&gt;/*&lt;/P&gt;&lt;P&gt;start MMRoot(x) global(_grid, _target);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; return( sum( probbnrm(_grid[,1], _grid[,2], x) ) - _target );&lt;/P&gt;&lt;P&gt;finish;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;start AltOrdFindRoot(P1, P2,&amp;nbsp; target) global(_grid, _target);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; N1 = countn(P1);&amp;nbsp;&amp;nbsp; N2 = countn(P2);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; q1 = OrdQuant(P1); q2 = OrdQuant(P2);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; v1 = q1[1:N1-1];&amp;nbsp;&amp;nbsp; v2 = q2[1:N2-1];&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; _grid = Expand2DGrid(v1, v2);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; _target = target;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; return( froot("MMRoot", {-1 1}) );&lt;/P&gt;&lt;P&gt;finish;&lt;/P&gt;&lt;P&gt;*/&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;/* OrdMVCorr: Compute a MVN correlation matrix from the PMF and &lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; the target correlation matrix for the ordinal variables. */&lt;/P&gt;&lt;P&gt;start OrdMVCorr(P, Corr);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; d = ncol(P);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; N = OrdN(P);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; mean = OrdMean(P);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; var&amp;nbsp; = OrdVar(P);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; cdf&amp;nbsp; = OrdCDF(P);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; R = I(d);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; do i = 1 to d-1;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sumCDFi = sum(cdf[1:N&lt;I&gt;-1, i]); &lt;/I&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; do j = i+1 to d;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sumCDFj = sum(cdf[1:N&lt;J&gt;-1, j]); &lt;/J&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; hStar = Corr[i,j] * sqrt(var&lt;I&gt;*var&lt;J&gt;) + mean&lt;I&gt;*mean&lt;J&gt; &lt;/J&gt;&lt;/I&gt;&lt;/J&gt;&lt;/I&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; - N&lt;I&gt;*N&lt;J&gt; + N&lt;I&gt;*sumCDFj + N&lt;J&gt;*sumCDFi;&lt;/J&gt;&lt;/I&gt;&lt;/J&gt;&lt;/I&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; R[i,j] = OrdFindRoot(P[,i], P[,j], hStar);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; R[j,i] = R[i,j];&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; end;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; end;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; return(R);&lt;/P&gt;&lt;P&gt;finish;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;/* RandMVOrdinal: &lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; N&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Number of desired observations from MV ordinal distribution, &lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; P&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Matrix of PMF for ordinal vars. The j_th col is the j_th PMF.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Use missing vals if some vars have fewer values than others.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; Corr&amp;nbsp; Desired correlation matrix for ordinal variables. Not every&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; matrix is a valid as the correlation of ordinal variables. */&lt;/P&gt;&lt;P&gt;start RandMVOrdinal(N, P, Corr);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; d = ncol(P);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; C = OrdMVCorr(P, Corr);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* 1. compute correlation matrix, C&amp;nbsp; */&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; mu = j(1, d, 0);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; X = RandNormal(N, mu, C);&amp;nbsp;&amp;nbsp; /* 2. simulate X ~ MVN(0,C)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; */&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; N = OrdN(P);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; quant = OrdQuant(P);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* compute normal quantiles for PMFs */&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; do j = 1 to d;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* 3. convert to ordinal&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; */&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; X[,j] = bin(X[,j], .M // quant[1:N&lt;J&gt;,j]);&lt;/J&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; end;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; return(X);&lt;/P&gt;&lt;P&gt;finish;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;store module=_all_;&lt;/P&gt;&lt;P&gt;quit;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;proc iml;&lt;/P&gt;&lt;P&gt;load module=_all_;&lt;/P&gt;&lt;P&gt;p={0.16 0.16,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; 0.28 0.28,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; 0.2&amp;nbsp; 0.2 ,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; 0.15 0.15,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; 0.12 0.12,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; 0.06 0.06,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; 0.03 0.03 };&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;delta={1.0 0.5,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0.5 1.0};&lt;/P&gt;&lt;P&gt;call randseed(1234);&lt;/P&gt;&lt;P&gt;x=RandMVOrdinal(60,p,delta);&lt;/P&gt;&lt;P&gt;create mn from x;append from x; close mn;&lt;/P&gt;&lt;P&gt; *****************************************************************************************************************************************;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 14pt;"&gt;&lt;STRONG&gt;Chapter 12.3.1 provided an example of adding random effect for a continuous variable. I am not sure if I could just use the same method. Do you guys have any code already for Ordinal Variables? If not, could you please provide any guidance on this? How would you control the random components?&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt; *****************************************************************************************************************************************;&lt;/P&gt;&lt;P&gt;/*code in Chapter 12.3.1*/&lt;/P&gt;&lt;P&gt;/*simple random effect model with repeated measurements*/&lt;/P&gt;&lt;P&gt;%let var_A=4;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /*variance of random effect (intercept)&amp;nbsp; */&lt;/P&gt;&lt;P&gt;%let sigma2=2;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /*variance of residual, N(0, sqrt(sigma2))&amp;nbsp; */&lt;/P&gt;&lt;P&gt;%let L=3;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /*num levels in random effect A*/&lt;/P&gt;&lt;P&gt;%let K=5;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /*num repeated measurements in each level of A */&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;data randomeffects(12345);&lt;/P&gt;&lt;P&gt;call streaminit(12345);&lt;/P&gt;&lt;P&gt;mu=5;&lt;/P&gt;&lt;P&gt;do a=1 to &amp;amp;L;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; rndA=rand("Normal", 0, sqrt(&amp;amp;var_A));&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; do rep=1 to &amp;amp;k;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; y= mu +rndA+rand("Normal", 0, sqrt(&amp;amp;sigma2));&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; output;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; end;&lt;/P&gt;&lt;P&gt;end;&lt;/P&gt;&lt;P&gt;run;&lt;/P&gt;&lt;P&gt; *****************************************************************************************************************************************;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 14pt;"&gt;&lt;STRONG style="color: #575757;"&gt;Look forward to your guidance,&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 14pt;"&gt;&lt;STRONG style="color: #575757;"&gt;Thanks,&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 14pt;"&gt;&lt;STRONG style="color: #575757;"&gt;Fred&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/BODY&gt;&lt;/HTML&gt;</description>
      <pubDate>Fri, 10 Apr 2015 15:13:02 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Procedures/Question-on-Simulating-Correlated-Ordinal-Data-with-Random/m-p/193213#M48505</guid>
      <dc:creator>FredXu</dc:creator>
      <dc:date>2015-04-10T15:13:02Z</dc:date>
    </item>
    <item>
      <title>Re: Question on Simulating Correlated Ordinal Data with Random effect</title>
      <link>https://communities.sas.com/t5/SAS-Procedures/Question-on-Simulating-Correlated-Ordinal-Data-with-Random/m-p/193214#M48506</link>
      <description>&lt;HTML&gt;&lt;HEAD&gt;&lt;/HEAD&gt;&lt;BODY&gt;&lt;P&gt;I think you need to carefully specify the statistical model from which you are trying to simulate. Presumably the random effect is changing some aspect of the model that varies between subjects.&amp;nbsp; You need to specify what changes between subjects and how it changes.&amp;nbsp; For each subject, you can draw a pair of observations. Then generate new parameters for the next subject, and repeat.&amp;nbsp; If that process sounds like what you are trying to acheive, then you do not need to change any functions.&amp;nbsp; You would loop over subjects and generate the PMF (P) and correlation for that subject, simulate from those parameters, and move on to the next subject.&lt;/P&gt;&lt;/BODY&gt;&lt;/HTML&gt;</description>
      <pubDate>Mon, 13 Apr 2015 17:13:13 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Procedures/Question-on-Simulating-Correlated-Ordinal-Data-with-Random/m-p/193214#M48506</guid>
      <dc:creator>Rick_SAS</dc:creator>
      <dc:date>2015-04-13T17:13:13Z</dc:date>
    </item>
  </channel>
</rss>

