/* Sampling bias in measures of income segregation simulation Authors: sean f reardon, Stanford University Joseph B. Townsend, Stanford Universityish Date: May 4, 2018 About: This simulation tests a bias correction for sample-based measures of segregation. In this simulation we test the correction on two measures of income segregation: the information theory index, or H, and the variance ratio index, or R, as well as their rank-order correlaries. The bias corrections tested here are detailed in: Reardon, S.F., Bischoff, K., Owens, A., & Townsend, J.B. (2018). Has Income Segregation Really Increased? Bias and Bias Correction in Sample-Based Segregation Estimates (CEPA Working Paper No.18-02). Retrieved from Stanford Center for Education Policy Analysis: http://cepa.stanford.edu/wp18-02 In order to ensure that our simulations capture the range of data- generating conditions that arise in practical applications, we use observed tabulations from the 2005-2009 American Community Survey in generating simulated data. Specifically, we do the following. First, we select all census tracts in a given metropolitan area. For each census tract, the ACS provides a tabulation of the estimated family income distribution, with income reported in 16 discrete ordered categories. Second, we construct a simulated population data file using the ordered categories, where each observation represents a single family in a tract with income in a category, and where the grouped income distribution in each tract is defined by the ACS-reported tabulations. We treat this population as the `true’ population of the metropolitan area; from it we compute the `true’ binary and rank-order segregation indices in this population. Third, for a given sampling rate 𝑟, we draw without replacement samples from each tract. From this sample, we estimate the unadjusted binary and rank-order segregation measures and their adjusted analogs. We repeat this step 100 times, producing a distribution of uncorrected segregation estimates and a distribution of adjusted segregation estimates. Finally, we repeat this process for each of the 380 metropolitan areas (excluding Puerto Rico) and for sampling rates ranging from 𝑟 = 0.02 to 𝑟 = 0.20. We then calculate the error in both the uncorrected and corrected estimates by comparing them to the `true' level of segregation. Data: The data file used in the simulation is assumed to have the following field names: metro: this is the unit variable tract: tracts are sub-units in metros; each observation ought to be one tract inc??: these are counts of members in each inc category within a tract. Our range is inc1-inc16 tot: count of members in each tract r0: this is optional; it is the real sampling rate Example data are available here: https://cepa.stanford.edu/content/has-income-segregation-really-increased-bias-and-bias-correction-sample-based-segregation-estimates .ado files: The user must have version 3.00 of seg.ado and 3.10 of rankseg.ado available. These may be installed by typing in Stata's command window: ssc install seg.ado ssc install rankseg.ado Tips: The user is advised that the simulation goes very slowly if the combined population of the units (e.g. the total population of all the metros in the data) in the data is very large. To increase speed, the user may consider breaking up the data into smaller sets of units (e.g. metros), and running these smaller sets individually. */ clear all timer clear set more off pause on set seed 8457321 ** USER SETTINGS ** *--------------------------------------------------------------------------- * please provide path to data glob DATA_PATH "your path here" * please provide name for data file glob DATA_NAME "prepped_ACS0509_tract.dta" * provide name for the output data glob SAVENAME "simulation output" * do you want to use real sample rates (1=yes) * to use these, they must be available in the loaded data glob realSAMP = 1 * simulation parameters *---------------------- * rlist is sampling rates to simulate * reps is how many replications per rate * hord tells rankseg the polynomial to use in fitting segregation function glob rlist "2 4 6 8 10 12 14 16 18 20" glob reps = 100 glob hord = 4 ** END USER SETTINGS ** *--------------------------------------------------------------------------- *--------------------------------------------------------------------------- ** BEGIN SIMULATION ** *--------------------------------------------------------------------------- * load the data *-------------- use "${DATA_PATH}/${DATA_NAME}", clear *--------------------------------------------------------------------------- * some preliminaries * adjust rlist, if needed if ${realSAMP}==1 { glob rlist "0 ${rlist}" loc rKeep "r0" } else loc rKeep "" * first determine number of inccats/K loc true = 1 loc topcat = 0 while `true' { capture su inc`=`topcat'+1' if _rc==0 loc ++topcat else loc true = 0 } * di "`topcat'" glob K = `topcat' glob K1 = `topcat' - 1 * don't need actual tract nums, simplify qui replace tract = _n * list of metros into global macro qui levelsof metro, loc(mts) clean glob METROS "`mts'" * end prelims *--------------------------------------------------------------------------- *--------------------------------------------------------------------------- * calculate stats of interest related to "real" data qui { bysort metro: egen tbar = mean(tot) bysort metro: gen J = _N preserve bysort metro: egen tsd = sd(tot) bysort metro: egen tskew = skew(tot) bysort metro: egen tkurt = kurt(tot) bysort metro: keep if _n==1 keep metro tbar tsd tskew tkurt tempfile metrostats save `metrostats', replace restore } // end qui loop * end stats of interest *--------------------------------------------------------------------------- *--------------------------------------------------------------------------- * treat data as real, calc true seg tempfile trueseg qui rankseg inc1-inc$K, h r ord(${hord}) tfile(`trueseg') by(metro) preserve qui { use `trueseg', clear rename e etrue rename h htrue rename h${hord} h${hord}true rename i itrue rename r rtrue rename r${hord} r${hord}true rename pctile ptrue keep metro thold *true sort metro thold order metro thold ptrue itrue etrue htrue rtrue tempfile trueseg save `trueseg', replace } // end qui loop restore * end true seg *--------------------------------------------------------------------------- *--------------------------------------------------------------------------- * next calc samp sizes per tract by samp rate qui keep metro tract inc? inc?? tot r0 *compute the sample sizes from each tract foreach r in $rlist { if `r'==0 { gen n`r' = round(tot*r0) qui drop r`r' gen double r`r' = n`r'/tot } else { g n`r' = round(tot*`r'/100) g double r`r' = n`r'/tot } } // end rlist loop tempfile metrodata qui save `metrodata', replace *metrodata file has metro-rate sample sizes and income cat cumulative percentages foreach r in $rlist { preserve qui { keep metro tract n`r' r`r' sort metro tract tempfile metroN`r' save `metroN`r'', replace *su } // end qui loop restore } * end bias calc *--------------------------------------------------------------------------- *--------------------------------------------------------------------------- * now sample qui keep metro tract inc? inc?? * make data "individual" level qui reshape long inc, i(metro tract) j(inccat) rename inc n qui drop if n==0 qui expand n qui compress sort metro tract tempfile metexpanded qui save `metexpanded', replace foreach r in $rlist { di "" di in ye "rate = `r'" loc rep = 1 while `rep' <= $reps { if int(`rep'/10) == `rep'/10 di in ye "`rep'" _c else di in gr "." _c preserve qui { use `metexpanded', clear merge m:1 metro tract using `metroN`r'' drop _merge keep metro tract inc* n`r' r`r' * sample using random number, then sort, keep desired size g rand = runiform() sort metro tract rand bysort metro tract: keep if _n<=n`r' * put data back into coarsened form g inc = 1 collapse (sum) inc, by(metro tract inccat r`r') fast reshape wide inc, i(tract r`r') j(inccat) forv k = 1/$K { replace inc`k' = 0 if inc`k' ==. } * calc seg on sampled data tempfile rate`r'rep`rep' rankseg inc1-inc$K, h r orders(${hord}) sampcounts rate(r`r') adjust adjustvars varlistpctiles tfile(`rate`r'rep`rep'') by(metro) replace use `rate`r'rep`rep'', clear g rate = `r' g rep = `rep' save `rate`r'rep`rep'', replace } // end qui loop restore loc ++rep } // end while rep loop } // end rlist loop * append all output data clear foreach r in $rlist { forv rep = 1/$reps { append using `rate`r'rep`rep'' } } * end sample *--------------------------------------------------------------------------- *--------------------------------------------------------------------------- * combine and clean everything up qui merge m:1 metro thold using `trueseg' *tab _merge drop _merge qui merge m:1 metro using `metrostats' drop _merge * fix some names rename se?${hord} ?${hord}_se rename se?${hord}_adj ?${hord}_adj_se rename *true *_true rename _* * tempfile rankOrderData qui save `rankOrderData', replace * end combine and clean up *--------------------------------------------------------------------------- * create error variables g h${hord}_err = h${hord} - h${hord}_true g r${hord}_err = r${hord} - r${hord}_true gen h${hord}_adj_err = h${hord}_adj - h${hord}_true gen r${hord}_adj_err = r${hord}_adj - r${hord}_true * order and label vars rename p_true pctile_true order /// metro rate rep thold /// pctile_true i_true e_true h_true r_true h${hord}_true r${hord}_true /// tmean /// t1harm /// hrate nmean /// B Bwo Bwr /// pctile i e h r /// h_adj /// r_adj /// h${hord} h${hord}_se r${hord} r${hord}_se /// h${hord}_adj h${hord}_adj_se r${hord}_adj r${hord}_adj_se /// h${hord}_err r${hord}_err /// h${hord}_adj_err r${hord}_adj_err /// tbar tsd tskew tkurt label var metro "metro num" lab var rate "sampling rate" lab var rep "simulation replication number" lab var thold "cat threshold" lab var pctile_true "pctile at top of thold cat" lab var tmean "mean of tract totals" lab var t1harm "harmonic mean of tot-1" lab var hrate "harmonic mean of samp rate" lab var B "bias factor used in adj" lab var Bwo "bias w/o replacement" lab var Bwr "bias w/ replacement" lab var pctile "pctile (samp)" lab var i "Norm. Int. (samp)" lab var e "Entropy (samp)" lab var h "Inf. Theory (samp)" lab var r "Rel. Diver. (samp)" lab var h_adj "Inf. Theory, bias adj (samp)" lab var r_adj "Rel. Diver., bias adj (samp)" lab var h${hord}_err "h${hord} - h${hord}_true" lab var r${hord}_err "r${hord} - r${hord}_true" lab var h${hord}_adj_err "h${hord}_adj - h${hord}_true" lab var r${hord}_adj_err "r${hord}_adj - r${hord}_true" *--------------------------------------------------------------------------- ** END SIMULATION ** *--------------------------------------------------------------------------- save "${DATA}/${SAVENAME}.dta", replace di in green "simulation complete"