Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

glance.ivreg fails with multiple endogenous regressors #599

Closed
lukesonnet opened this issue Feb 5, 2019 · 4 comments
Closed

glance.ivreg fails with multiple endogenous regressors #599

lukesonnet opened this issue Feb 5, 2019 · 4 comments
Labels
beginner-friendly bug an unexpected problem or unintended behavior

Comments

@lukesonnet
Copy link
Contributor

lukesonnet commented Feb 5, 2019

glance::ivreg(., diagnostics = TRUE) will fail if the 2SLS has multiple endogenous regressors. This is due to the fact that summary.ivreg(., diagnostics = TRUE) will return a diagnostics matrix that has no row named "Weak instruments", which is required in the following line:

statistic.weakinst = diagnostics["Weak instruments", "statistic"],

library(broom)
library(AER)
# Works
glance(ivreg(mpg ~ hp | qsec + am, data = mtcars), diagnostics = TRUE)
# Fails
glance(ivreg(mpg ~ hp + wt | qsec + am, data = mtcars), diagnostics = TRUE)

As you can see in the latter case if you do summary(ivreg(mpg ~ hp + wt | qsec + am, data = mtcars)), the diagnostics have two rows named "Weak instruments (hp)" and "Weak instruments (wt)" instead of "Weak instruments", because the first-stage fstat is separate for each endogenous regressor.

This crash should be avoided by either a workaround that fails to return the f-stats or a solution that returns them all. Of course, returning them all means having an unexpected number of columns in the return, which is undesirable.

Thoughts? I encountered this while looking at mimicking glance.ivreg in estimatr::glance.iv_robust.

@IndrajeetPatil
Copy link
Contributor

Here is a reprex for the issue mentioned above-

set.seed(123)
library(broom) 
library(AER) 
#> Loading required package: car
#> Loading required package: carData
#> Loading required package: lmtest
#> Loading required package: zoo
#> 
#> Attaching package: 'zoo'
#> The following objects are masked from 'package:base':
#> 
#>     as.Date, as.Date.numeric
#> Loading required package: sandwich
#> Loading required package: survival

# Works 
glance(ivreg(mpg ~ hp | qsec + am, data = mtcars), diagnostics = TRUE) 
#> # A tibble: 1 x 13
#>   r.squared adj.r.squared sigma statistic p.value    df statistic.Sargan
#>       <dbl>         <dbl> <dbl>     <dbl>   <dbl> <int>            <dbl>
#> 1     0.592         0.578  3.92      38.5 7.92e-7     2             12.8
#> # ... with 6 more variables: p.value.Sargan <dbl>,
#> #   statistic.Wu.Hausman <dbl>, p.value.Wu.Hausman <dbl>,
#> #   statistic.weakinst <dbl>, p.value.weakinst <dbl>, df.residual <int>

# Fails 
glance(ivreg(mpg ~ hp + wt | qsec + am, data = mtcars), diagnostics = TRUE)
#> Error in diagnostics["Weak instruments", "statistic"]: subscript out of bounds

And traceback-

> traceback()
9: eval_tidy(xs[[i]], unique_output)
8: lst_quos(xs, transform = expand_lst)
7: tibble(statistic.Sargan = diagnostics["Sargan", "statistic"], 
       p.value.Sargan = diagnostics["Sargan", "p-value"], statistic.Wu.Hausman = diagnostics["Wu-Hausman", 
           "statistic"], p.value.Wu.Hausman = diagnostics["Wu-Hausman", 
           "p-value"], statistic.weakinst = diagnostics["Weak instruments", 
           "statistic"], p.value.weakinst = diagnostics["Weak instruments", 
           "p-value"])
6: eval(substitute(expr), data, enclos = parent.frame())
5: eval(substitute(expr), data, enclos = parent.frame())
4: with.default(s, tibble(statistic.Sargan = diagnostics["Sargan", 
       "statistic"], p.value.Sargan = diagnostics["Sargan", "p-value"], 
       statistic.Wu.Hausman = diagnostics["Wu-Hausman", "statistic"], 
       p.value.Wu.Hausman = diagnostics["Wu-Hausman", "p-value"], 
       statistic.weakinst = diagnostics["Weak instruments", "statistic"], 
       p.value.weakinst = diagnostics["Weak instruments", "p-value"]))
3: with(s, tibble(statistic.Sargan = diagnostics["Sargan", "statistic"], 
       p.value.Sargan = diagnostics["Sargan", "p-value"], statistic.Wu.Hausman = diagnostics["Wu-Hausman", 
           "statistic"], p.value.Wu.Hausman = diagnostics["Wu-Hausman", 
           "p-value"], statistic.weakinst = diagnostics["Weak instruments", 
           "statistic"], p.value.weakinst = diagnostics["Weak instruments", 
           "p-value"]))
2: glance.ivreg(ivreg(mpg ~ hp + wt | qsec + am, data = mtcars), 
       diagnostics = TRUE)
1: glance(ivreg(mpg ~ hp + wt | qsec + am, data = mtcars), diagnostics = TRUE)

@alexpghayes alexpghayes added bug an unexpected problem or unintended behavior beginner-friendly labels Mar 3, 2019
@weiyangtham
Copy link
Contributor

I'm interested in taking this issue on. After talking with @alexpghayes, one possible solution is to not return the F-stat as part of glance() and have it returned from tidy instead. Let's have tidy return either the endogenous variables or the instruments by including an argument tidy(instruments = TRUE).

@alexpghayes
Copy link
Collaborator

Closed in #641!

@github-actions
Copy link

This issue has been automatically locked. If you believe you have found a related problem, please file a new issue (with a reprex: https://reprex.tidyverse.org) and link to this issue.

@github-actions github-actions bot locked and limited conversation to collaborators Mar 11, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
beginner-friendly bug an unexpected problem or unintended behavior
Projects
None yet
Development

No branches or pull requests

4 participants