Skip to contents

The accessors a fitted model answers to, defined for the class new_ipw() constructs.

  • coef() returns the effect estimates.

  • vcov() returns the covariance of those estimates.

  • confint() returns their confidence limits.

  • nobs() returns the number of observations the outcome model was fitted on.

  • df.residual() returns the residual degrees of freedom the fitted variance object reports.

  • weights() returns the weights the outcome model was fitted with.

  • model.frame() returns the outcome model's model frame.

  • estimand() returns the estimand the weights targeted.

Usage

# S3 method for class 'ipw'
coef(object, ..., effects = NULL)

# S3 method for class 'ipw'
vcov(object, ..., effects = NULL)

# S3 method for class 'ipw'
confint(object, parm, level = 0.95, ..., effects = NULL)

# S3 method for class 'ipw'
nobs(object, ...)

# S3 method for class 'ipw'
df.residual(object, ...)

# S3 method for class 'ipw'
weights(object, ...)

# S3 method for class 'ipw'
model.frame(formula, ...)

# S3 method for class 'ipw'
estimand(x, ...)

Arguments

object

An ipw object.

...

Further arguments. These methods ignore them.

effects

The reading to report, either "marginal" or "conditional". NULL, the default, reports the reading the result records; any other value overrides it for the one call and leaves the result as it is.

parm

The rows to report an interval for, given either as the labels of the reported surface or as their positions in it. Missing means all of them.

level

The confidence level. At the level the result stores, its own limits are returned; at any other level they are recomputed.

formula

An ipw object. The model.frame() generic in stats names its first argument formula, and the method matches it.

x

An ipw object. The estimand() generic names its first argument x, and the method matches it.

Value

coef() returns a named numeric vector of effect estimates, one element per row of the estimates frame, named by effect label. In the conditional reading it returns the outcome model's coefficients as that model reports them, names included.

vcov() returns the square numeric covariance matrix of those estimates, with the effect labels as dimnames on both margins, exactly as the fitting package attached it. A result that records no such matrix raises an error of class causalgenerics_no_vcov rather than returning one built from the standard errors, which would report the effects as uncorrelated. In the conditional reading it returns the corrected covariance of the outcome model's coefficients, in the order coef() reports them whatever order it was attached in. An outcome model that was never wrapped raises an error of class causalgenerics_no_conditional_vcov, a wrapped model that no longer carries the covariance raises an error of class causalgenerics_no_vcov_ipw_model, and a covariance whose labels cannot be paired with the coefficients raises an error of class causalgenerics_conditional_vcov_mismatch.

confint() returns a matrix with one row per effect parm selects, in the order parm gives them, and two columns holding the lower and upper limit. The rows are named by effect label and the columns by the two tail probabilities as percentages, the way the confint() methods in stats name theirs. A character parm that names an effect the result does not report raises an error of class causalgenerics_invalid_argument. In the conditional reading the rows are the outcome model's coefficients, which parm names and indexes in the same two ways, and the limits are the normal ones built from the corrected covariance at every level, since the limits the result stores belong to the effects the marginal reading reports.

coef(), vcov(), and confint() raise an error of class causalgenerics_invalid_argument_effects when effects names neither reading, and when the result's own field does.

nobs() returns a single integer, the number of observations the outcome model was fitted on, which is the number the estimates were computed from and not necessarily the number the weighting model saw.

df.residual() returns the residual degrees of freedom the fitted variance object reports, as an integer when that number is a whole one an integer can hold and as the double the object gave when it is not. A fractional count is what a penalized or smooth fit spends, and it comes back as it stands rather than truncated to a count the fit did not spend. NA_integer_ comes back when the result records no fitted variance object or that object reports no residual degrees of freedom.

weights() returns the outcome model's weights as its model frame stores them, so a concrete weight class such as psw comes back as itself, or NULL when the outcome model was fitted unweighted.

model.frame() returns the outcome model's model frame, which is the data the reported estimates were computed from. The (weights) column a weighted frame carries is deliberately dropped, since tooling that reads the columns of a frame as the variables a model was fitted on, such as prediction and averaging packages, would otherwise treat the estimation weights as one of them; weights() is where those are reported. A model whose own method has no frame to give raises that model's error rather than one of this package's.

estimand() returns the estimand the result records, which is the one the weights the estimates were computed under targeted. There is deliberately no estimand<-() method for a result: assigning a new estimand would relabel those estimates rather than recompute them, so a caller who writes the assignment is told that no method exists.

Details

These methods live here for the reason print() does. Two packages each registering coef.ipw() would collide in the shared S3 method table, and a caller writing against a result would then get whichever package was installed last rather than the contract.

Everything they read is part of the new_ipw() contract: the estimates frame, the ipw_vcov attribute attached to it, estimand, outcome_mod, fit, and the effects field the section below describes. They never branch on se_method, since the fields they read already hold the result of whatever computation that names, and they reach into fit only through ordinary S3 dispatch. A package whose variance object is a bare list rather than a fitted model therefore uses them unchanged.

Rows are named by the effect labels the new_ipw() contract defines, so the name coef() gives an estimate is the one vcov() and confint() use for it and the one print() labels its row with.

The reading these methods report

coef(), vcov(), and confint() report the surface the result's effects field names, and take an effects argument that names one for a single call. The marginal reading is the causal contrast estimates, which is what these methods reported before the field existed and what a result that records no mode still reports. The conditional reading is the outcome model's coefficient surface: coef() gives the model's coefficients, vcov() gives their covariance, and confint() bounds them.

The covariance the conditional reading reports is the block of the joint estimation that the fitting package attached with new_ipw_model(), never the one the outcome model computed for itself. A model fitted as though its weights were fixed understates its uncertainty, because the weights were estimated from the same data, so there is nothing to fall back on when no corrected block is there. vcov() and confint() refuse the reading instead, and name which of the two ways the block can be missing they met. An outcome model that was never wrapped raises an error of class causalgenerics_no_conditional_vcov, which the package that produced the result answers by wrapping the outcome model with new_ipw_model() before it builds the result. An outcome model that carries the wrapper class with no covariance behind it raises an error of class causalgenerics_no_vcov_ipw_model, since a model that is already wrapped has nothing to gain from being wrapped again and the object itself is what is wrong. All of these carry the general class causalgenerics_no_vcov. coef() needs no such block and reports the coefficients either way.

The block and the coefficients are paired by name, and the block is reported in coefficient order whatever order it was attached in, so the variance read beside a coefficient is that coefficient's. A block whose labels cannot be paired with the coefficients raises an error of class causalgenerics_conditional_vcov_mismatch. A block of another size, one labeled with the parameter names of a stacked system, and a model whose coefficients carry no names are the three ways the pairing fails. Reading such a block by position instead would report the covariance of other parameters under this model's coefficient names.

nobs(), df.residual(), weights(), model.frame(), and estimand() describe the fit rather than a surface of it, so they answer the same way in either reading and take no effects argument.

See also

new_ipw() for the result class and the fields these methods read.

Examples

dat <- data.frame(
  x = rep(c(-1.5, -0.5, 0.5, 1.5), each = 5),
  z = rep(c(0, 1), 10),
  y = rep(c(0, 1, 1, 0, 1), 4)
)

ps <- fitted(glm(z ~ x, family = binomial(), data = dat))
wts <- ifelse(dat$z == 1, 1 / ps, 1 / (1 - ps))

# Written out literally, in the shape the `ipw()` return contract documents.
estimates <- data.frame(
  effect = c("rd", "log(rr)"),
  estimate = c(0.199882, 0.560414),
  std.err = c(0.092425, 0.273519),
  z = c(2.1626, 2.0489),
  ci.lower = c(0.018732, 0.024326),
  ci.upper = c(0.381032, 1.096502),
  conf.level = 0.95,
  p.value = c(0.030570, 0.040470)
)

# The covariance of the two effects, which a method attaches to the estimates
# it returns. Both are computed from the same weighted means, so the
# off-diagonal entry is far from zero.
attr(estimates, "ipw_vcov") <- matrix(
  c(0.008542, 0.022753, 0.022753, 0.074813),
  nrow = 2,
  dimnames = list(estimates$effect, estimates$effect)
)

res <- new_ipw(
  estimand = "ate",
  wt_mod = glm(z ~ x, family = binomial(), data = dat),
  outcome_mod = glm(y ~ z, family = quasibinomial(), data = dat, weights = wts),
  estimates = estimates,
  se_method = "linearization",
  fit = NULL
)

coef(res)
#>       rd  log(rr) 
#> 0.199882 0.560414 
vcov(res)
#>               rd  log(rr)
#> rd      0.008542 0.022753
#> log(rr) 0.022753 0.074813

# At the stored level the stored limits come back.
confint(res)
#>            2.5 %   97.5 %
#> rd      0.018732 0.381032
#> log(rr) 0.024326 1.096502

# At any other level they are recomputed.
confint(res, parm = "rd", level = 0.9)
#>          5 %      95 %
#> rd 0.0478564 0.3519076

nobs(res)
#> [1] 20

# The linearization path records no fitted variance object.
df.residual(res)
#> [1] NA

head(weights(res))
#> [1] 1.785796 2.272594 1.785796 2.272594 1.785796 2.083669

# The data the estimates were computed from, without the `(weights)` column
# the fitting machinery stored beside the variables the formula named.
head(model.frame(res))
#>   y z
#> 1 0 0
#> 2 1 1
#> 3 1 0
#> 4 0 1
#> 5 1 0
#> 6 0 1

estimand(res)
#> [1] "ate"

# The conditional reading reports the outcome model's coefficient surface
# rather than the effects.
coef(res, effects = "conditional")
#>  (Intercept)            z 
#> 3.919028e-01 1.012353e-15 

# Its covariance is the corrected block a fitting package attaches to the
# outcome model. This one carries none, and the covariance the model computed
# for itself is not a substitute: it treats the estimated weights as fixed.
try(vcov(res, effects = "conditional"))
#> Error in vcov.ipw(res, effects = "conditional") : 
#>   The conditional reading reports the covariance the joint estimation of the weights and the outcome implies, and this result's outcome model records none; the package that produced the result attaches one by wrapping the model with `new_ipw_model()`.

outcome_mod <- glm(y ~ z, family = quasibinomial(), data = dat, weights = wts)

# Standing in for the outcome block of a stacked sandwich, which a method
# computes from the estimating equations of both steps.
corrected <- vcov(outcome_mod) * 1.4

conditional <- as_conditional(new_ipw(
  estimand = "ate",
  wt_mod = glm(z ~ x, family = binomial(), data = dat),
  outcome_mod = new_ipw_model(outcome_mod, corrected),
  estimates = estimates,
  se_method = "linearization",
  fit = NULL
))

# A result that records the conditional reading answers in it with nothing
# named at the call site.
coef(conditional)
#>  (Intercept)            z 
#> 3.919028e-01 1.012353e-15 
vcov(conditional)
#>             (Intercept)         z
#> (Intercept)    0.646421 -0.646421
#> z             -0.646421  1.292842
confint(conditional)
#>                 2.5 %   97.5 %
#> (Intercept) -1.183914 1.967720
#> z           -2.228542 2.228542