@@ -12,6 +12,10 @@ a unit weight and λ is a time period weight.
1212
1313The implementation follows the author's reference implementation in the R package `synthdid`.
1414
15+ NOTE: The implementation assumes that the outcomes and treatment matrices are sorted such that
16+ treated units come last in both `Y` and `W`. It therefore checks whether `W` is sorted and swaps
17+ rows in both `Y` and `W` to sort both matrices accordingly if required.
18+
1519"""
1620struct SyntheticDiD{T1}# <: SCM where T1
1721 tp:: T1
@@ -35,27 +39,63 @@ function isfitted(x::SyntheticDiD)
3539 all (! iszero, x. τ̂) || all (! iszero, x. se_τ̂)
3640end
3741
38- function fit! (x:: SyntheticDiD{BalancedPanel{SingleUnitTreatment{Continuous}}} )
42+ function fit! (x:: SyntheticDiD{BalancedPanel{SingleUnitTreatment{Continuous}}} ;
43+ se = nothing )
3944 (;Y, W) = x. tp
4045
4146 T₀ = length_T₀ (x. tp)
4247 N₁ = 1 # length(treated_ids(x)) - has to be one given type of BalancedPanel in this method
4348 N₀ = size (Y, 1 ) - N₁
4449
4550 # Implementation of synthdid below assumes that treated unit comes last
46- swaprows! (Y, treated_ids (x. tp), size (Y, 1 ))
51+ if ! issorted (any (x) for x ∈ eachrow (W))
52+ treated_row = treated_ids (x. tp)
53+ swaprows! (Y, treated_row, size (Y, 1 ))
54+ swaprows! (W, treated_row, size (W, 1 ))
55+ end
4756
4857 # Get estimate and store in SyntheticDiD object
4958 estimate = synthdid_estimate (Y, N₀, T₀)
5059 x. τ̂ .= estimate. τ̂
5160 x. λ̂ .= estimate. λ̂
5261 x. ω̂ .= estimate. ω̂
5362
63+ if ! isnothing (se)
64+ if se != :placebo
65+ error (" Only placebo standard error estimation is currently implemented" )
66+ else
67+ V̂ = get_V̂_τ (x). V̂
68+ x. se_τ̂ .= √ (V̂)
69+ end
70+ end
71+
5472 # return SynhtDiD object
5573 return x
5674end
5775
5876
77+ function get_V̂_τ (x:: SyntheticDiD{BalancedPanel{SingleUnitTreatment{Continuous}}} )
78+ (;Y, W) = x. tp
79+
80+ Y_untreated = Y[Not (treated_ids (x. tp)), :]
81+
82+ T₀ = length_T₀ (x. tp)
83+ N₁ = 1
84+ N₀ = size (Y_untreated, 1 ) - N₁
85+
86+ τ̂s = zeros (N₀)
87+
88+ for i ∈ 1 : N₀- 1
89+ swaprows! (Y_untreated, i, size (Y_untreated, 1 ))
90+ τ̂s[i] = synthdid_estimate (Y_untreated, N₀, T₀). τ̂
91+ end
92+
93+ swaprows! (Y_untreated, 1 , size (Y_untreated, 1 ))
94+ τ̂s[end ] = synthdid_estimate (Y_untreated, N₀, T₀). τ̂
95+
96+ return (V̂ = var (τ̂s), τ̂s = τ̂s)
97+ end
98+
5999function synthdid_estimate (Y, N₀, T₀;
60100 ω_intercept = true , λ_intercept = true ,
61101 max_iter = 10_000 , max_iter_pre_sparsify = 100 , sparsify_function = sparsify_weights!)
196236
197237
198238function swaprows! (X:: AbstractMatrix , i:: Integer , j:: Integer )
199- @inbounds for k = 1 : size (X,2 )
239+ @inbounds for k = axes (X,2 )
200240 X[i, k], X[j, k] = X[j, k], X[i, k]
201241 end
202242end
0 commit comments