Skip to content

PyFixest 0.10.7: Basic Did2s support#194

Merged
s3alfisc merged 26 commits intomasterfrom
did
Nov 1, 2023
Merged

PyFixest 0.10.7: Basic Did2s support#194
s3alfisc merged 26 commits intomasterfrom
did

Conversation

@s3alfisc
Copy link
Copy Markdown
Member

@s3alfisc s3alfisc commented Oct 22, 2023

  • Adds support for experimental event_study() function, which supports Difference-in-Differences estimation via two-way fixed effects and Gardner's two-stage estimator (2021).
  • To support the implementation of Gardner's estimator, now allows to estimate 'shallow' models as feols("Y ~ 0 | f1).

To Do's:

  • allow for covariates
  • allow for custom clustering variables
  • implement proper event study with leads and lags. Pyfixest's i() operator currently only supports one reference level, do I have to adjust it to add a second level? Check.
  • Write unit tests.

Example:

%load_ext autoreload
%autoreload 2
from pyfixest.experimental.did import event_study
from pyfixest.summarize import summary
import pandas as pd

df_het = pd.read_csv("pyfixest/data/df_het.csv")

fit_twfe = event_study(
    data = df_het,
    yname = "dep_var",
    idname= "state",
    tname = "year",
    gname = "g",
    estimator = "twfe"
)

fit_did2s = event_study(
    data = df_het,
    yname = "dep_var",
    idname= "state",
    tname = "year",
    gname = "g",
    estimator = "did2s"
)

summary([fit_twfe, fit_did2s])

# ###
#
# Estimation:  TWFE
# Dep. var.: dep_var, Fixed effects: state+year
# Inference:  CRV1
# Observations:  46500
#
# | Coefficient   |   Estimate |   Std. Error |   t value |   Pr(>|t|) |   2.5 % |   97.5 % |
# |:--------------|-----------:|-------------:|----------:|-----------:|--------:|---------:|
# | zz00_treat    |      2.135 |        0.044 |    48.803 |      0.000 |   2.049 |    2.220 |
# ---
# ###
#
#   Estimation:  DID2S
# Dep. var.: dep_var
# Inference:  CRV1 (GMM)
# Observations:  46500
#
# | Coefficient   |   Estimate |   Std. Error |   t value |   Pr(>|t|) |   2.5 % |   97.5 % |
# |:--------------|-----------:|-------------:|----------:|-----------:|--------:|---------:|
# | zz00_treat    |      2.152 |        0.048 |    45.208 |      0.000 |   2.059 |    2.246 |
# ---

@s3alfisc
Copy link
Copy Markdown
Member Author

@kylebutts on one hand, mostly fyi =) But also, some of the code is more or less directly translated from your R package, which I mention in the codebase. I think it would be best practice to actually add your name to the list of package authors (this is what I do with in my R packages if I more or less copy code from another package). What do you think?

@s3alfisc s3alfisc mentioned this pull request Oct 22, 2023
5 tasks
@s3alfisc s3alfisc linked an issue Oct 22, 2023 that may be closed by this pull request
@kylebutts
Copy link
Copy Markdown

I'm not sure how multiple inheritance works in python, but is there a possibility to pass first_stage and second_stage directly? For example, I'm not sure how I could specify subgroup-specific time-trends in that notation. The nice thing about did2s (IMO) is the flexibility in modeling $Y_{it}(0)$.

Though, I do see how it's nice to have a single event_study option. Could you have a did2s command that event_study calls with the standard TWFE formula? Happy to try and help, but my python skills are not very strong.

@s3alfisc
Copy link
Copy Markdown
Member Author

Hi Kyle, Thanks for offering your help! I might have some questions on reference levels for the event study with leads and lags down the line =)

I thought about having a custom did2s function yesterday and basically came to the same conclusion as you: I should definitely support it! It indeed offers a loot of versatility that event_study() cannot provide (as you mention, subgroup specific time trends, "pooling" of time intervals in event studies, triple DIDs and probably quite a few other things I am not aware of). It should be fairly straightforward to set up - basically I need to copy the event_study() interface and call it did2s and add formula arguments to it + DID2S.estimate(). And that's it I think =)

@s3alfisc
Copy link
Copy Markdown
Member Author

Ah, maybe not as easy as I thought: mapping from an event study interface to calling did2s is fairly straightforward, but not the other way around. But should still be manageable =)

@kylebutts
Copy link
Copy Markdown

What do you think is hard about making a did2s command? Your code looks pretty generic. From what I can tell, the main change you would need to make is in the vcov part:
https://github.com/s3alfisc/pyfixest/blob/f03deb3b8015efbdf7cfac9cda14f5c10db37830/pyfixest/experimental/did.py#L287-L291

@s3alfisc
Copy link
Copy Markdown
Member Author

Yes, you're right, it's just that the closer time gets to midnight, the faster I type and the worse I think 😅

basically, the steps are the following:

  • create a did2s function
  • Initiate the DID2S object
  • Overwrite the formula attributes with the user selected formulas
  • update estimate() and vcov()

Really not too hard :)

@s3alfisc s3alfisc changed the title PyFixest 0.10.5 PyFixest 0.10.7: Basic Did2s support Oct 29, 2023
@codecov
Copy link
Copy Markdown

codecov bot commented Oct 30, 2023

Codecov Report

All modified and coverable lines are covered by tests ✅

Comparison is base (0c3b162) 0.00% compared to head (7398f5e) 0.00%.

❗ Current head 7398f5e differs from pull request most recent head 04e4140. Consider uploading reports for the commit 04e4140 to get more accurate results

Additional details and impacted files
@@      Coverage Diff      @@
##   master   #194   +/-   ##
=============================
=============================

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@kylebutts
Copy link
Copy Markdown

lol I'm getting push notifications of each attempt @s3alfisc 😅 godspeed on this

@s3alfisc
Copy link
Copy Markdown
Member Author

Oh no 🙈 I had my fingers crossed GitHub would stop notifying you after the 10th attempt or so 🙃 sorry about that! I'm definitely done for today 😅

@s3alfisc s3alfisc merged commit dccce10 into master Nov 1, 2023
s3alfisc added a commit that referenced this pull request Nov 18, 2023
* PyFixest 0.10.7: Basic Did2s support (#194)

* initial commit

* reproduce did2s.r results

* add twfe estimator

* create treatment var internally

* some defensive input checks

* acknowledge kyle as copyright holder

* create experimental folder

* update docs

* update version

* add did2s function

* get event_study() did2s to work again

* delete did2s function

* add basic tests

* patch version

* delete pyaches

* update news

* update starting message

* update readme

* update pyproject.toml

* ci tests on mac as fixest already compiled

* test on windows

* back to testing on linux

* first install python, then R deps

* fix yaml syntax

* yaml is too hard

* fix typo

* PyFixest 0.10.8: More flexible DID2s support (#206)

* initial commit

* reproduce did2s.r results

* add twfe estimator

* create treatment var internally

* some defensive input checks

* acknowledge kyle as copyright holder

* create experimental folder

* update docs

* update version

* add did2s function

* get event_study() did2s to work again

* delete did2s function

* add basic tests

* patch version

* delete pyaches

* update news

* update starting message

* update readme

* update pyproject.toml

* ci tests on mac as fixest already compiled

* test on windows

* back to testing on linux

* first install python, then R deps

* fix yaml syntax

* yaml is too hard

* some work towards a more flexible API

* get did2s function prototype to run

* event_study() and did2s() both run through

* add examples to did2s() and event_study()

* more tests for did2s

* pass tests

* two reference levels

* fix small bug re _drop_ref

* get did2s() to run

* fix did2s vcov bug

* add tests

* update did example

* further updates

* update i-tests

* bump version and update readme

* readme tweaks

* update news

* update readme

* update readme

* dont gitignore figures folder

* PyFixest 0.8.10.1: add black workflow (#207)

* add black action

* run black

* revert notebook

* PyFixest 0.10.8.2: close #208 (#209)

* check for did2s if treatment is boolean

* update docs

* ci only when push to master

* bump version

* small fixes

* formatting

* PyFixest 0.10.9: Improve etable() (#210)

* first step to prettier etable

* add tabulate dependency, fix etable fixef bug

* fix bug with no fixed effects

* fix no model has fixef exception

* bump poetry version

* fix hline placement bug

* formatting

* make plot nicer

* add vcov info

* reformat

* reformat

* update news

* PyFixest 0.10.10  (#212)

* attempt to fix #211

* cleanup

* clarification

* fix i() bug for i(var), not for i(var1, var2)

* add drop_intercept argument to feols, fepois

* fix error with did2s inference

* add error when 0 or -1 in first stage

* fix tests, output warning for i(var1, var2) syntax

* format code

* update figure + fix small bug

* no 0 in second stage did test

* bump version

* deprecate i(var1, var2) syntax, update news

* format

* bring back i(var1, var2)

* format

* fix i(var1, var2) interaction - unit tests pass

* formatting

* bump version

* Fix poisson bug (#215)

* update docs

* add _depvar attribute to Feols object

* use _depvar attribute

* move separation checks out of Fepois to fix #138

* revert changes to performance method

* temporarily do not report r squared metrics

* fix separation bug  #138

* formatting

* update docs

* njit and parallelize crv1 inference #204

* formatting

* bump version
damandhaliwal pushed a commit to damandhaliwal/pyfixest that referenced this pull request Jun 17, 2025
* initial commit

* reproduce did2s.r results

* add twfe estimator

* create treatment var internally

* some defensive input checks

* acknowledge kyle as copyright holder

* create experimental folder

* update docs

* update version

* add did2s function

* get event_study() did2s to work again

* delete did2s function

* add basic tests

* patch version

* delete pyaches

* update news

* update starting message

* update readme

* update pyproject.toml

* ci tests on mac as fixest already compiled

* test on windows

* back to testing on linux

* first install python, then R deps

* fix yaml syntax

* yaml is too hard
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Did2s (Gardner)

2 participants