/* This programs uses Monte Carlo Simulation to compute the Multi-nomial Clustering Statistic proposed by Rysman and Greenstein (Economic Letters 2003) P-value for Two sided test BUG FIX by CESARE RIGHI 02-01-2017 */ /* 1) Copy the file to your ado directory 2) Make sure the filename extension is .ado not .txt!! 3) syntax is "mtad [varlist], m(varname) n(iterations) wide "mtad y, m(market) [if choice data is a single categorical variable] "mtad y1 y2 y3..., m(market) wide [if choice data is a series of dummy vars] */ program define mtad, rclass version 9 syntax [varlist] [if], Mkt(varname) [PRobs(numlist >0 <1) NIter(integer 50) wide] quietly { preserve ** Step 0: SET UP THE DATA capture keep `if' keep `varlist' `mkt' if "`wide'" == "wide" { tab `mkt' if r(N)>r(r) { noi disp "Wide data must have 1 obs per market" exit } local numVals = wordcount("`varlist'") if (`numVals' < 2) { noi disp "Must specify at least two choices" exit } local i = 1 foreach X in `varlist' { rename `X' choice`i' local i = `i' + 1 } } else { if (wordcount("`varlist'") >1) { noi disp "Choice data must be a single categorical variable" exit } rename `varlist' tmp tab tmp, gen(choice) local numVals = r(r) collapse (sum) choice*, by(`mkt') } ** Step 1: BASELINE PROBABILITIES * User provided if "`probs'" != "" { if "`wide'" != "wide" { noi disp "List of probabilities allowed only for wide format data" exit } if (wordcount("`probs'") != `numVals') { noi disp "Must specify a probability for each choice:" `numVals' exit } scalar checksum = 0 local i=1 foreach num of numlist `probs' { local lnPchoice`i' = log(`num') scalar checksum = checksum + `num' local i = `i' + 1 } if checksum != 1 { noi disp "Probablities must sum to 1" exit } egen ttl = rowtotal(choice*) } * Global Means else { egen ttl = rowtotal(choice*) sum ttl local denom = r(sum) foreach V of varlist choice* { sum `V' local lnP`V' = log(r(sum)/`denom') } } ** Step 2 : RANDOM CHOICE LIKELIHOOD gen logLm = lnfact(ttl) foreach V of varlist choice* { replace logLm = logLm - lnfact(`V') + `V'*`lnP`V'' } ** Step 3 : MONTE CARLO SIMULATION sum ttl local rMax = r(max) local i = 1 local tmp = 0 g cut0 = 0 foreach V of varlist choice* { g cut`i' = `tmp' + exp(`lnP`V'') local tmp = `tmp' + exp(`lnP`V'') local i = `i' + 1 } local i = 0 while `i' < `niter' { foreach V of varlist choice* { g tmp`V' = 0 } local j = 1 while `j' <= `rMax' { g rnds = uniform() local m = 0 local n = 1 foreach V of varlist choice* { replace tmp`V' = tmp`V' + 1 if ((cut`m' < rnds) & (cut`n' >= rnds) & (ttl >=`j')) local m = `m'+1 local n = `n'+1 } drop rnds local j=`j'+1 } gen tmplogLm = lnfact(ttl) foreach V of varlist choice* { replace tmplogLm = tmplogLm - lnfact(tmp`V') + tmp`V'*`lnP`V'' } sum tmplogLm g iter`i' = r(mean) if (_n==1) drop tmp* if (mod(`i',50) == 0 & `i'>0) { noi display "Iteration `i'..." } local i = `i' + 1 } ** Step 4 : Output sum logLm return scalar logl = r(mean) return scalar N = r(N) egen tmp1 = rmean(iter*) sum tmp1 return scalar elogl = r(mean) egen tmp2 = rsd(iter*) sum tmp2 return scalar sd = r(mean) local z = (return(logl)-return(elogl))/return(sd) local p = 2*(1-normal(abs(`z'))) noi display " " noi display as result "Observed Likelihood:" %8.3f return(logl) noi display as result "Expected Likelihood:" %8.3f return(elogl) noi display as result "Standard Deviation:" %8.3f return(sd) noi display as result "z = " %5.3f `z' " P>|z| = " %5.2f `p' noi display " " if (`z' < 0 & `p' < 0.05) { noi display as result "Result: Agglomeration" return local mtad = "Agglomeration" } if (`z' > 0 & `p' < 0.05) { noi display as result "Result: Dispersion" return local mtad = "Dispersion" } noi display as result "Random choice simulated using " `i' " draws" restore } end