Showing posts with label xtreg. Show all posts
Showing posts with label xtreg. Show all posts

May 8, 2024

Mummolo & Peterson (2018): Fixed-effects regression


set scheme lean1 webuse nlswork, clear xtset idcode year // Model of interest: xtreg ln_w ttl_exp age c.age#c.age tenure c.tenure#c.tenure not_smsa south i.year, fe local b : display %4.2f _b[ttl_exp] // Isolate relevant variation in the treatment: reghdfe ttl_exp, absorb(idcode year) residuals(relevantvariation) // Identify a plausible counterfactual shift in X given the data: center ttl_exp sum relevantvariation local sd1 : display %4.2f r(sd) sum ttl_exp local sd2 : display %4.2f r(sd) twoway (kdensity c_ttl_exp) /// (kdensity relevantvariation), /// ytitle("Density") xtitle(Treatment (centered around 0)) /// title("{bf:A} Treatment distribution", span bexpand justification(left)) /// legend(order(1 "Original distribution, {it:SD} = `sd2'" /// 2 "Distribution after FE, {it:SD} = `sd1'" ) /// pos(2) ring(0)) /// name(figure1A, replace) // Calculate range within individuals bysort idcode: egen max = max(ttl_exp) bysort idcode: egen min = min(ttl_exp) generate range = max - min drop max min qui sum range, detail local mean : display %4.2f r(mean) local p95 : display %4.2f r(p95) twoway (histogram range, freq) /// (scatteri 2000 `mean' (3) "Mean = `mean'", msymbol(i)) /// (scatteri 2000 `p95' (3) "95th percentile = `p95'" , msymbol(i)), /// title("{bf:B} Within-individual range of treatment", span bexpand justification(left)) /// ylabel(, format(%7.0gc)) ytitle(Frequency) /// xline(`mean') xline(`p95') /// xtitle(Within-individual range) legend(off) /// name(figure1B, replace) graph combine figure1A figure1B, col(2) // Calculate % of cases where treatment does not vary egen pickone = tag(idcode) fre range if pickone // In 12% of cases the treatment does not vary // Multiply the estimated coefficient of interest by the revised standard deviation display "Estimated coefficient of interest = `b'" display "Within-standard deviation = `sd1'" display "Product = " _skip(1) `sd1' * `b'
Reference Mummolo, Jonathan, and Erik Peterson. 2018. "Improving the Interpretation of Fixed Effects Regression Results." Political Science Research and Methods 6(4):829-835. doi: 10.1017/psrm.2017.44

Feb 15, 2018

Multiple imputation of longitudinal data

This allows replicating the third example in Allison (2002, pp. 74-76).
// MI Example 3

use "https://statisticalhorizons.com/wp-content/uploads/hip.dta", clear
drop if wave == 4 // Not sure these are the correct data

xtset sid 

preserve
drop if missing(cesd, srh, adl, walk, pain)
bysort sid: drop if _N < 3
eststo clear
eststo: xtreg cesd srh walk adl pain ib3.wave, fe
restore

preserve

eststo: xtreg cesd srh walk adl pain ib3.wave, fe
restore

preserve
mi set mlong
mi register impute cesd srh walk adl pain wave

mi impute mvn cesd srh walk adl pain wave, ///
   add(10) burnin(500) burnbetween(30) 

eststo: mi estimate, post: xtreg cesd srh walk adl pain ib3.wave, fe
restore

preserve

reshape wide adl pain srh walk cesd, i(sid) j(wave)
mi set mlong
mi register impute cesd* srh* walk* adl* pain*

mi impute mvn cesd* srh* walk* adl* pain*, ///
   add(10) burnin(500) burnbetween(200)

mi reshape long adl pain srh walk cesd, i(sid) j(wave)
eststo: mi estimate, post: xtreg cesd srh walk adl pain ib3.wave, fe
restore

// Table 6.4

esttab, wide se nonumbers mtitle("LD by person" "LD by person-wave" "MI by person-wave" "MI by person")

Reference

Allison, Paul D. 2002. Missing Data. Sage. doi: 10.4135/9781412985079

Aug 2, 2017

Analyzing natural policy experiments

Hu et al. 2017 simulate data of a natural policy experiment and show how to analyze the data with regression adjustment, propensity score matching, difference-in-differences, and fixed effects regression. (The paper also includes IV, regression discontinuity, and interrupted time series, but does not describe the data created for these analyses.)

clear
set seed 2

// Create data set with experimental conditions
input str4 educ str6 sex str9 treatmentstr str4 health1 number
      Low  Male   Exposed   Poor   333
      Low  Male   Exposed   Good   917
      Low  Male   Unexposed Poor  1000
      Low  Male   Unexposed Good  2750   
      Low  Female Exposed   Poor   500
      Low  Female Exposed   Good  3250  
      Low  Female Unexposed Poor   167 
      Low  Female Unexposed Good  1083
      High Male   Exposed   Poor    83
      High Male   Exposed   Good   542
      High Male   Unexposed Poor   584
      High Male   Unexposed Good  3791
      High Female Exposed   Poor   125 
      High Female Exposed   Good  1750
      High Female Unexposed Poor   208
      High Female Unexposed Good  2917
end

expand number  // Create full number of cases

// Transform strings to numerical variables
generate loeduc    = (educ         == "Low")
generate female    = (sex          == "Female")
generate treatment = (treatmentstr == "Exposed")
generate good1     = (health1      == "Good")
label define loeduc 0 "High" 1 "Low"
label val loeduc loeduc
label define female 0 "Male" 1 "Female"
label val female female
label define treatment 0 "Unexposed" 1 "Exposed"
label val treatment treatment
label define health 0 "Poor" 1 "Good"
label val good1 health

// Simulate outcome variable
generate good2 = good1
replace  good2 =       1 if good1 == 0 & loeduc == 1 & (runiform() <= .05)
replace  good2 =       1 if good1 == 0 & loeduc == 0 & (runiform() <= .20)
replace  good2 =       1 if good1 == 0 & treatment == 1 & (runiform() <= .30)
label val good2 health

// Transform some more and clean up
generate poor2 = (good2 == 0)
generate poor1 = (good1  == 0)
drop educ sex treatmentstr health1 number good1 good2

// Table 1-ish
table poor2, by(loeduc female treatment) contents(freq) 

// 1) Regression adjustment
logit poor2 treatment female if loeduc == 0, or
logit poor2 treatment female if loeduc == 1, or
logit poor2 treatment##loeduc female##loeduc, or

// 2) Propensity score matching
teffects nnmatch (poor2 female) (treatment) if loeduc == 0
teffects nnmatch (poor2 female) (treatment) if loeduc == 1

// 3) Difference in difference
  // Transform to long format
gen id = _n
reshape long poor, i(id) j(year)

logit poor treatment##c.year if loeduc == 0, or 
logit poor treatment##c.year if loeduc == 1, or 
logit poor loeduc##treatment##c.year, or 

// 4) Fixed effects model
replace treatment = 0 if year == 1

xtset id year
xtreg poor treatment year if loeduc == 0, fe 
xtreg poor treatment year if loeduc == 1, fe 
xtreg poor treatment##loeduc year##loeduc, fe 

Reference

Hu, Yannan, Frank J. van Lenthe, Rasmus Hoffmann, Karen van Hedel, and Johan P. Mackenbach. 2017. "Assessing the Impact of Natural Policy Experiments on Socioeconomic Inequalities in Health. How to Apply Commonly Used Quantitative Analytical Methods?" BMC Medical Research Methodology 17(1):68. doi: 10.1186/s12874-017-0317-5