version 14.2 mata: /* Native Stata/Mata estimator implementation. Rows entering the numerical routines are assignment units. T is the expanded cluster outcome and N the represented size (both individual quantities when N=1). */ struct sreg_result { real rowvector b real matrix V, beta, betalarge, bsmall, Vsmall, bbig, Vbig real scalar adjusted, design, k, nsmall, nbig, psmall } real scalar sreg_api_version() { return(1) } void sreg_fail(string scalar msg) { errprintf("sreg: %s\n", msg) _error(498) } void sreg_warn(string scalar msg) { printf("{txt}Warning: %s\n", msg) st_local("sreg_warnings", st_local("sreg_warnings")+msg+" | ") } real colvector sreg_ids(real colvector s) { real colvector z, ordering real matrix info real scalar j if(!rows(s)) return(J(0,1,.)) ordering=order((s,(1::rows(s))),(1,2)) info=panelsetup(s[ordering],1); z=J(rows(s),1,.) for(j=1;j<=rows(info);j++) z[ordering[|info[j,1]\info[j,2]|]]=J(info[j,2]-info[j,1]+1,1,j) return(z) } real scalar sreg_modal(real colvector sizes, real scalar k) { real colvector u real scalar modal, best, j, freq u=uniqrows(sort(sizes,1)); modal=.; best=0 if(rows(u)==1) { if(k!=. & k!=u[1]) sreg_fail("The supplied small-stratum size k does not match the observed stratum size.") return(u[1]) } for(j=1;j<=rows(u);j++) if(k==. ? u[j]<=3 : u[j]==k) { freq=mean(sizes:==u[j]) if(freq>=.25 & freq>best) { modal=u[j] best=freq } } if(modal==.) sreg_fail("Invalid input: Either all strata are large or too few strata qualify as small. Omit smallstrata or specify the appropriate k().") return(modal) } // Classify strata by size for estimator selection. real colvector sreg_classify(real colvector sizes, real scalar k) { real scalar modal modal=sreg_modal(sizes,k) if(rows(uniqrows(sort(sizes,1)))>1) sreg_warn(sprintf("Mixed design detected: at least 25%% of all strata have the same size (k = %g). Weighted estimators will be used.",modal)) return(sizes:==modal) } real colvector sreg_slope(real colvector y, real matrix X) { real matrix Z Z=J(rows(X),1,1),X if (rank(Z)0; out.design=0; out.k=. return(out) } /* Bilinear paired-strata variance and cross-treatment covariances. */ real scalar sreg_small_cross(real colvector U, real colvector V, real colvector S, real colvector D, real scalar fac) { real scalar h, n, a, r, s, j, rho, cv, ans real matrix su, sv, grouped, info, sums real colvector ur, vr, ix, ids real rowvector gu, gv, counts h=max(S); n=rows(S); a=max(D)+1 su=sv=J(h,a,0); gu=gv=counts=J(1,a,0); ans=0 for(r=0;r0; out.design=1; out.k=n/h return(out) } struct sreg_result scalar sreg_fit(real colvector T, real colvector S, real colvector D, real colvector N, real matrix X, real scalar hc, real scalar small, real scalar k, real scalar cluster) { struct sreg_result scalar out, lo, hi real colvector sizes, us, flag, il, ih real matrix info real scalar s,h, modal, j, weight, sharevar, nn real rowvector delta h=max(S); info=panelsetup(sort(S,1),1) sizes=info[,2]-info[,1]:+1 us=uniqrows(sort(sizes,1)) if(!small) { if(rows(us)==1 & us[1]<=5) sreg_warn("All strata have the same small number of assignment units, but smallstrata was not specified.") for(j=1;j<=rows(us);j++) if((k==. ? us[j]<=3 : us[j]==k) & mean(sizes:==us[j])>=.25) { sreg_warn("At least 25% of strata are small, but smallstrata was not specified; consider the small/mixed procedure."); break } return(sreg_large(T,S,D,N,X,hc,1)) } if(rows(us)==1) { if(k!=. & k!=us[1]) sreg_fail("The supplied small-stratum size k does not match the observed stratum size.") return(sreg_small(T,S,D,N,X,hc,cluster)) } flag=sreg_classify(sizes,k) modal=min(select(sizes,flag)) flag=flag[S]; il=selectindex(flag); ih=selectindex(!flag) lo=sreg_small(T[il],sreg_ids(S[il]),D[il],N[il],X[il,.],hc,cluster) if(cols(X)) { for(s=1;s<=h;s++) if(sizes[s]!=modal) for(j=0;j<=max(D);j++) { nn=sum((S:==s):&(D:==j)) if(nn0; out.design=2; out.k=modal out.nsmall=rows(il); out.nbig=rows(ih); out.psmall=weight return(out) } void sreg_run(string scalar yv, string scalar dv, string scalar sv, string scalar gv, string scalar nv, string scalar xv, string scalar sample, real scalar hc, real scalar small, real scalar k) { real matrix X, agg, xx, info real colvector Y,D,S,G,N,u,ix, ordering real scalar n,j,p,cl,changed struct sreg_result scalar out Y=st_data(.,yv,sample); D=st_data(.,dv,sample); n=rows(Y) S=(sv=="" ? J(n,1,1) : st_data(.,sv,sample)) X=(xv=="" ? J(n,0,.) : st_data(.,tokens(xv),sample)) cl=(gv!=""); p=cols(X) if(small & sv=="") sreg_fail("Strata indicator variable has not been provided; smallstrata requires strata().") if(any(D:!=floor(D)) | any(S:!=floor(S))) sreg_fail("Strata and treatment must contain only integer values.") if(min(S)!=1) sreg_fail("The strata should be indexed by {1, 2, 3, ...}.") if(min(D)!=0) sreg_fail("The treatments should be indexed by {0, 1, 2, ...}, with control coded 0.") if(rows(uniqrows(sort(S,1)))!=max(S) | rows(uniqrows(sort(D,1)))!=max(D)+1) sreg_fail("Variables S and D must not contain skipped values within the range.") if(max(D)<1) sreg_fail("At least one active treatment and a control arm are required.") N=J(n,1,1) if(cl) { G=st_data(.,gv,sample) if(any(G:!=floor(G))) sreg_fail("Cluster identifiers must contain only integer values.") if(nv!="") { N=st_data(.,nv,sample) if(any(N:!=floor(N))) sreg_fail("Cluster sizes must contain only integer values.") if(min(N)<=0) sreg_fail("Cluster sizes must be positive.") } else sreg_warn("Cluster sizes have not been provided; using the number of available observations in every cluster.") // Stable grouping avoids scanning every observation for each cluster. ordering=order((G,(1::n)),(1,2)) Y=Y[ordering]; S=S[ordering]; D=D[ordering]; G=G[ordering] N=N[ordering]; X=X[ordering,.] info=panelsetup(G,1); u=G[info[,1]] agg=J(rows(u),4+p,.); changed=0 for(j=1;j<=rows(u);j++) { ix=(info[j,1]::info[j,2]) if(min(S[ix])!=max(S[ix]) | min(D[ix])!=max(D[ix]) | min(N[ix])!=max(N[ix])) sreg_fail("The values for S, D, and Ng must be consistent within each cluster.") agg[j,1..4]=(mean(Y[ix]),S[ix[1]],D[ix[1]],(nv=="" ? rows(ix) : N[ix[1]])) if(p) { xx=X[ix,.]; agg[j,5..(4+p)]=mean(xx) if(any(colmin(xx):!=colmax(xx))) changed=1 } } if(changed) sreg_warn("sreg cannot use individual-level covariates for cluster adjustment; covariates have been aggregated to their cluster-level averages.") Y=agg[,1]; S=agg[,2]; D=agg[,3]; N=agg[,4] X=(p ? agg[,5..(4+p)] : J(rows(Y),0,.)) } out=sreg_fit(Y:*N,S,D,N,X,hc,small,k,cl) if(any(out.b:>=.) | any(out.V:>=.)) sreg_fail("Nonfinite estimates or variance; check treatment cells and adjustment identification.") st_matrix(st_local("b"),out.b); st_matrix(st_local("V"),out.V) if(cols(out.beta)) st_matrix(st_local("beta"),out.beta) st_numscalar(st_local("nunits"),rows(Y)); st_numscalar(st_local("nstrata"),max(S)) st_numscalar(st_local("adjusted"),out.adjusted); st_numscalar(st_local("design"),out.design) st_numscalar(st_local("ksmall"),out.k) if(out.design==2) { if(cols(out.betalarge)) st_matrix(st_local("betabig"),out.betalarge) st_matrix(st_local("bs"),out.bsmall); st_matrix(st_local("Vs"),out.Vsmall) st_matrix(st_local("bb"),out.bbig); st_matrix(st_local("Vb"),out.Vbig) st_numscalar(st_local("ps"),out.psmall) st_numscalar(st_local("ns"),out.nsmall); st_numscalar(st_local("nb"),out.nbig) } } end