英文:
Why is the confidence interval different when using tidy() on output of aggte() than what aggte() itself displays?
问题
I am working with the did
package performing an estimation using the conditional parallel trends assumption with only one treated group (and 7 control groups that are never treated), so only one treatment adoption time.
我正在使用did
包进行估计,使用条件平行趋势假设,只有一个受试组(以及7个从未受试的对照组),因此只有一个治疗采纳时间。
I use the aggte()
function with type = "simple"
to compute the ATT. R then displays confidence bands for the MP
-object. If I however try to access the estimate, standard error and the confidence bands with the function tidy()
on the same MP
-object, tidy()
returns different confidence bands.
我使用aggte()
函数以type = "simple"
计算ATT。然后,R显示了MP
对象的置信区间。但是,如果我尝试使用相同的MP
对象上的tidy()
函数来访问估计值、标准误差和置信区间,tidy()
返回不同的置信区间。
I tried setting type= "group"
, but still the confidence bands are different.
我尝试将type = "group"
,但仍然得到不同的置信区间。
Any help is appreciated!
感谢任何帮助!
英文:
I am working with the did
package performing an estimation using the conditional parallel trends assumption with only one treated group (and 7 control groups that are never treated), so only one treatment adoption time.
I use the aggte()
function with type = "simple"
to compute the ATT. R then displays confidence bands for the MP
-object. If I however try to access the estimate, standard error and the confidence bands with the function tidy()
on the same MP
-object, tidy()
returns different confidence bands.
I tried setting type= "group"
, but still the confidence bands are different.
Any help is appreciated!
library(did)
data(mpdta)
mw.attgt.X <- att_gt(yname = "lemp",
gname = "first.treat",
idname = "countyreal",
tname = "year",
xformla = ~lpop,
data = mpdta,
)
mw.attgt.X
aggte(mw.attgt.X, type = "simple")
tidy(aggte(mw.attgt.X, type = "simple"))
aggte(mw.attgt.X, type = "group")
tidy(aggte(mw.attgt.X, type = "group"))
You can see the discrepancy in the confidence intervals.
答案1
得分: 1
tidy
函数最初来自{broom}
软件包,现在已经包含在tidymodels宇宙中。其目标是整理(因此称为broom,用于扫除和清理)模型对象。模型对象被重塑为数据框,这样,比如说,如果你用100个模型进行编程,它们可以被压缩成一个数据框并一起进行分析。
看起来did
包重新导出了broom
中的tidy
通用函数并添加了它自己的方法。查看tidy
方法的源代码可能非常具有信息性。函数定义非常冗长,所以我会截取对你的用例真正重要的部分。
请注意conf.low
和conf.high
是如何计算的。将其与AAGTEobj本身的显示方式进行比较。经过一些调查,你可以看到调用了did:::summary.AGGTEobj
函数。再次为简洁起见进行截断。
在这里,你可以看到置信区间是如何计算的。我不是处理差异的专家,但看起来它们在两种方法中的计算方式是不同的。
个人认为这种差异值得报告错误。
英文:
The tidy
function is one that originally comes from the package {broom}
that now lives in the tidymodels universe. It's goal is to tidy-up (hence broom, for sweeping and cleaning) model objects. The model object is reshaped into a data frame so that, say you're doing this programmatically with a 100 models they can be squished together into a dataframe and analysed together.
It looks like the did
package reexports the tidy
generic function from broom
and adds its own methods. Taking a look at the source code of the tidy
method can be quite informative. The function definition is quite verbose so I'm going to truncate it to what really matters for your use case.
did:::tidy.AGGTEobj
#> function (x, ...)
#> {
#> . . . TRUNCATED . . .
#> if (x$type == "simple") {
#> out <- data.frame(type = x$type, estimate = x$overall.att,
#> std.error = x$overall.se, conf.low = x$overall.se -
#> stats::qnorm(1 - x$DIDparams$alp/2) * x$overall.se,
#> conf.high = x$overall.se + stats::qnorm(1 - x$DIDparams$alp/2) *
#> x$overall.se, point.conf.low = x$overall.se -
#> stats::qnorm(1 - x$DIDparams$alp/2) * x$overall.se,
#> point.conf.high = x$overall.se + stats::qnorm(1 -
#> x$DIDparams$alp/2) * x$overall.se)
#> }
#> out
#> }
#> <bytecode: 0x116f88558>
#> <environment: namespace:did>
<sup>Created on 2023-04-20 with reprex v2.0.2</sup>
Note how conf.low
and conf.high
are calculated. Compare this to how the AAGTEobj is printed itself. After some sleuthing you can see that the did:::summary.AGGTEobj
function is called. Again, truncating for brevity.
Here you can see how the confidence bands are calculated. I'm no expert in difference in difference but it looks like the way that they are calculated for both methods are different.
did:::summary.AGGTEobj
#> function (object, ...)
#> {
#> . . . TRUNCATED . . .
#> pointwise_cval <- qnorm(1 - alp/2)
#> overall_cband_upper <- object$overall.att + pointwise_cval *
#> object$overall.se
#> overall_cband_lower <- object$overall.att - pointwise_cval *
#> object$overall.se
#> out1 <- cbind.data.frame(object$overall.att, object$overall.se,
#> overall_cband_lower, overall_cband_upper)
#> out1 <- round(out1, 4)
#> overall_sig <- (overall_cband_upper < 0) | (overall_cband_lower >
#> 0)
#> overall_sig[is.na(overall_sig)] <- FALSE
#> overall_sig_text <- ifelse(overall_sig, "*", "")
#> out1 <- cbind.data.frame(out1, overall_sig_text)
#> . . . TRUNCATED . . .
#> cband_text1a <- paste0(100 * (1 - object$DIDparams$alp),
#> "% ")
#> cband_text1b <- ifelse(object$DIDparams$bstrap, ifelse(object$DIDparams$cband,
#> "Simult. ", "Pointwise "), "Pointwise ")
#> cband_text1 <- paste0("[", cband_text1a, cband_text1b)
#> cband_lower <- object$att.egt - object$crit.val.egt *
#> object$se.egt
#>
#> . . . TRUNCATED . . .
#> }
#> }
#> <bytecode: 0x1107b1758>
#> <environment: namespace:did>
<sup>Created on 2023-04-20 with reprex v2.0.2</sup>
Personally, I think the difference is worth a bug report.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论