Learning Objectives

Following this assignment students should be able to:

  • Implement first differencing and demeaning manually
  • Run one-way fixed effects using LSDV, xtreg, and reghdfe
  • Identify the staggered adoption problem in TWFE
  • Use modern TWFE estimators such as csdid

Reading

Topics

  • How fixed effects work
  • Individual intercepts
  • First differencing
  • De-meaning
  • Two-way fixed effects
  • Clustered standard errors

  • Reading (chapter 16): The Effect

Additional Suggested Readings (Recent TWFE Literature)

The literature on Two-Way Fixed Effects (TWFE) and staggered treatment adoption has evolved rapidly. To understand the issues with standard TWFE and modern estimators, see:

  • The Problem: Goodman-Bacon, A. (2021). “Difference-in-differences with variation in treatment timing.” Journal of Econometrics.
  • A Solution: Callaway, B., and Sant’Anna, P. H. (2021). “Difference-in-differences with multiple time periods.” Journal of Econometrics.
  • Accessible Overview: Baker, A. C., Larcker, D. F., and Wang, C. C. (2022). “How much should we trust staggered difference-in-differences estimates?” Journal of Financial Economics.

Lecture Notes

  1. One-Way Fixed Effects
  2. Two-Way Fixed Effects

Exercises

  1. First Differencing (20 pts)

    We will use the mm.dta dataset for these exercises. Recall that it is a panel dataset tracking agricultural households in Ethiopia over time. The panel identifier is qnno (household) and the time identifier is tindex (time index).

    • Load mm.dta.
    • Start by running a pooled OLS regression of yield on totfertcostha, clustering the standard errors at the qnno level.
    • Sort the dataset by the panel identifier (qnno) and the time variable (tindex).
    • Generate a first-differenced variable for yield d_yield (e.g., yield - yield[_n-1]) by qnno.
    • Generate a first-differenced variable for fertilizer input d_fert (e.g., totfertcostha - totfertcostha[_n-1]) by qnno.
    • Run a regression of the differenced yield on the differenced fertilizer variable, clustering the standard errors at the qnno level.

    1. Use eststo to save the pooled OLS and FD results. Then use esttab to create a table of results using the following table structure:

       esttab      ols fd using "$answ/11-fd.tex", replace ///
                        b(3) se(3) ///
                        rename(totfertcostha "Fertilizer Cost" d_fert "Fertilizer Cost") ///
                        keep("Fertilizer Cost") ///
                        star(* 0.10 ** 0.05 *** 0.01) ///
                        stats(N r2, labels("Observations" "R-squared") fmt(0 3)) ///
                        noobs booktabs nonum nomtitle collabels(none) ///
                        nobaselevels nogaps fragment label ///
                        prehead("\begin{tabular}{l*{2}{c}} " ///
                          "\\[-1.8ex]\hline \hline \\[-1.8ex] " ///
                          "& \multicolumn{1}{c}{OLS} & " ///
                          "\multicolumn{1}{c}{FD} \\ \midrule") ///
                        postfoot("\hline \hline \\[-1.8ex] " ///
                          "\multicolumn{3}{p{\linewidth}}{\small " ///
                          "\noindent \textit{Note}: Dependent variable " ///
                          "is chickpea yield in kg/ha. All models use " ///
                          "standard errors clustered at the " ///
                          "household level (in parentheses). " ///
                          "* p$<$0.10, ** p$<$0.05, *** p$<$0.01.} " ///
                          "\end{tabular}")
    

    2. What is the effect of a change in fertilizer cost on chickpea yield? How does it compare to the pooled OLS estimate?


  2. Demeaning the Data (10 pts)

    Using mm.dta:

    • Use egen with bysort qnno: to calculate the household-specific mean for yield.
    • Do the same to calculate the household-specific mean for fertilizer cost totfertcostha.
    • Generate demeaned versions of both variables by subtracting the household mean from the original value (e.g., dm_yield and dm_fert).
    • Run a regression of the demeaned yield on the demeaned fertilizer, clustering standard errors by qnno.
    1. Use eststo to save the demeaned results. Then adapt the table structure from the previous exercise to create a table of results with a third column headed Demean.
    2. What is the coefficient on fertilizer cost in the demeaned regression and how does it compare to the coefficients you calculated in Exercises 1?

  3. Dummy Variables (10 pts)

    Using tenuredata.dta (restricted to rice == 1):

    • Instead of manually demeaning the data, use the i. operator to include a fixed effect dummy for every individual household (panelid).
    • Run a regression of raw yield on q_f_ha and your dummy variables (i.panelid). Cluster the standard errors by panelid.

    Does the regression even run on your version of Stata? If so,

    1. Use eststo to save the LSDV results. Then adapt the table structure from the previous exercise to create a table of results with a fourth column headed LSDV.
    2. What is the coefficient on fertilizer in the LSDV regression and how does it compare to the coefficients you calculated in Exercises 1 and 2?

  4. Using `xtreg` (10 pts)

    Using mm.dta:

    • Tell Stata that your dataset is a panel using the xtset command. Specify qnno tindex as the panel identifiers.
    • Run a fixed effects regression of yield on totfertcostha using the xtreg command with the , fe option. Cluster standard errors at the qnno level.
    1. Use eststo to save the FE results. Then adapt the table structure from the previous exercise to create a table of results with a fifth column headed FE.
    2. What is the coefficient on fertilizer cost in the FE regression and how does it compare to the coefficients you calculated in Exercises 1-3?

  5. Adding Time Fixed Effects (10 pts)

    Using mm.dta, let’s extend our models from the One-Way FE lecture.

    • Ensure your data is xtset qnno tindex.
    • Run a standard One-Way Fixed Effects model. Regress yield on fertilizer cost (totfertcostha) using xtreg, fe. Cluster standard errors at the qnno level.
    • Run a standard Two-Way Fixed Effects model. Regress yield on fertilizer cost (totfertcostha) using xtreg, fe, but this time include time fixed effects by adding i.tindex to your list of covariates. Cluster standard errors at the qnno level.
    • Now estimate the exact same model using the reghdfe command. Specify absorb(qnno tindex) to absorb both individual and time fixed effects. Cluster standard errors at the qnno level.
    1. Use eststo to save each of the three results. Then adapt the table structure from the Exercise 1 to create a table of results heading columns with OWFE, TWFE, and reghdfe.
    2. How do the estimates on totfertcostha compare across the three models? Did aggregate time shocks bias the one-way fixed effect estimator?

  6. Staggered Adoption Cohorts (15 pts)

    Using mm.dta, we want to evaluate the effect of improved chickpea adoption (icp) on yield. However, parcels adopt improved chickpeas at different times. We need to create a variable that stores the first time period a parcel ever had icp == 1.

    • Sort the data by qnno and tindex.
    • Create a variable first_icp that equals tindex if icp == 1, and missing otherwise.
    • Use bysort qnno: to replace first_icp with the minimum value of first_icp for that parcel across all years (egen ... = min()).
    • For parcels that never adopted improved chickpeas (missing(first_icp)), replace first_icp = 0.

    You now have the exact cohort group variable needed for modern TWFE estimators. Run a TWFE regression using either xtreg with time dummies (i.tindex) or reghdfe and use eststo to save the result. What is the coefficient on improved chickpea adoption?


  7. Modern TWFE Estimators (20 pts)

    Let’s do a Bacon decomposition and then apply Callaway & Sant’Anna’s modern robust estimator to mm.dta using the first_icp cohort variable we just built.

    1. Run bacondecomp yield icp, ddetail. Save the resulting figure as a .png file and import it into your lastname.tex under Assignment 11. Give it the caption Bacon Decomposition and label it fig:bacon.
    2. Now run csdid yield, ivar(qnno) time(tindex) gvar(first_icp) tr(icp). Calculate the aggregated overall ATT by running estat event and use eststo to save the result. Then use esttab to create a table of the results from this model and the TWFE model you estimated in the last exercise.
    3. How do these results compare to the standard Two-Way Fixed Effects estimate you found in the last exercise?

  8. Check That Your Code Runs (5 pts)

    Sometimes you think you’re code runs, but it only actually works because of something else you did previously. To make sure it actually runs you should save your work and then run it in a clean environment.

    Follow these steps in to make sure your code really runs:

    1. Restart Stata by closing the instance of Stata that you have open.

    2. When you reopen Stata, type in the command line clear all. Or, better yet, put clear all at the top of your .do file, after the preamble but before any commands.

    3. Rerun your entire homework assignment by clicking the Execute button to make sure it runs from start to finish and produces the expected results.

    4. Make sure that you saved your code with the name of the assignment number (i.e., assignment_01). You should see the file in your git repo on your machine.

    5. Make sure that your code will run on other computers (relevant for all assignments after the first assignment)

      • No cd. Use a project.do file instead to set directories
      • Use only relative paths in files other than the project.do file
      • Use / not \ for paths

  9. Challenge 11 (Challenge - 20 pts)

    This challenge combines everything you’ve learned about Fixed Effects, estout, and coefplot to test the sensitivity of the icp coefficient across multiple Fixed Effect specifications.

    • Load the mm.dta dataset.
    • Run the following four models and store their estimates (e.g., eststo c1, etc.):
      • Model 1: Pooled OLS (reg). Regress yield on icp totfertcostha totchemcostha.
      • Model 2: Time Fixed Effects (reg). Add i.tindex to Model 1.
      • Model 3: One-Way Fixed Effects (xtreg, fe). Add xtset and run the model without time dummies.
      • Model 4: Two-Way Fixed Effects (xtreg, fe). Add i.tindex to Model 3.
    • For all 4 models, cluster the standard errors by qnno.
    1. Use esttab to create a table of the coefficient on icp across all four models. Adapt the table structure from Week 10, Exercise 4 to create a table of results. In your lastname.tex, include the table using \input{11-challenge-regs.tex} inside a table environment that I provide for Assignment 11 in Overleaf. Give the table a caption and label.
    2. Use coefplot to graph the coefficient on icp across all four models. Adapt the figure structure from Week 10, Exercise 7 to create a single figure of results. Add a horizontal line at 0 (xline(0)) and customize the legend to cleanly label the four models. In your lastname.tex, include the graph using \includegraphics[width=0.8\textwidth]{11-challenge-coefplot.png} inside a figure environment. Give the graph a caption and label.

Assignment submission checklist

Solutions

  1. First Differencing 1, 2
  2. Demeaning the Data 1, 2
  3. Dummy Variables 1, 2
  4. Using xtreg 1, 2
  5. Adding Time Fixed Effects 1, 2
  6. Staggered Adoption Cohorts
  7. Modern Estimators 1, 2, 3
  8. Check That Your Code Runs
  9. Challenge 11 1, 2