set_confound {CausalQueries}R Documentation

Set confound

Description

Adjust parameter matrix to allow confounding.

Usage

set_confound(model, confound = NULL, add_confounds_df = TRUE)

Arguments

model

A causal_model. A model object generated by make_model.

confound

A named list. It relates nodes to statements that identify causal types with which they are confounded

add_confounds_df

Logical. Attach a dataframe with confound links. Defaults to TRUE.

Details

Confounding between X and Y arises when the nodal types for X and Y are not independently distributed. In the X -> Y graph, for instance, there are 2 nodal types for X and 4 for Y. There are thus 8 joint nodal types:

|          | t^X                |                    |           |
|-----|----|--------------------|--------------------|-----------|
|     |    | 0                  | 1                  | Sum       |
|-----|----|--------------------|--------------------|-----------|
| t^Y | 00 | Pr(t^X=0 & t^Y=00) | Pr(t^X=1 & t^Y=00) | Pr(t^Y=00)|
|     | 10 | .                  | .                  | .         |
|     | 01 | .                  | .                  | .         |
|     | 11 | .                  | .                  | .         |
|-----|----|--------------------|--------------------|-----------|
|     |Sum | Pr(t^X=0)          | Pr(t^X=1)          | 1         |

This table has 8 interior elements and so an unconstrained joint distribution would have 7 degrees of freedom. A no confounding assumption means that Pr(t^X | t^Y) = Pr(t^X), or Pr(t^X, t^Y) = Pr(t^X)Pr(t^Y). In this case there would be 3 degrees of freedom for Y and 1 for X, totalling 4 rather than 7.

set_confounds lets you relax this assumption by increasing the number of parameters characterizing the joint distribution. Using the fact that P(A,B) = P(A)P(B|A) new parameters are introduced to capture P(B|A=a) rather than simply P(B).

The simplest way to allow for confounding is by adding a bidirected edge, such as via: set_confound(model, list('X <-> Y')). In this case the descendent node has a distribution conditional on the value of the ancestor node.

Ordering of conditioning can also be controlled however via set_confound(model, list(X = 'Y')) in which case X is given a distribution conditional on nodal types of Y.

More specific confounding statements are also possible using causal syntax. A statement of the form list(X = 'Y[X=1]==1') can be interpreted as: 'Allow X to have a distinct conditional distribution when Y has types that involve Y[X=1]==1.' In this case nodal types for Y would continue to have 3 degrees of freedom. But there would be parameters assigning the probability of X when t^Y = 01 or t^Y=11 and other parameters for residual cases. Thus 6 degrees of freedom in all. This is still short of an unconstrained distribution, though an unconstrained distribution can be achieved with repeated application of statements of this form, for instance via list(X = 'Y[X=1]>Y[X=0]'), X = 'Y[X=1]==Y[X=0]').

Similarly a statement of the form list(Y = 'X==1') can be interpreted as: 'Allow Y to have a distinct conditional distribution when X=1.' In this case there would be two distributions over nodal types for Y, producing 2*3 = 6 degrees of freedom. Nodal types for X would continue to have 1 degree of freedom. Thus 7 degrees of freedom in all, corresponding to a fully unconstrained joint distribution.

Value

An object of class causal_model. It essentially returns a list containing the elements comprising a model (e.g. 'statement', 'nodal_types' and 'DAG') with the parameter matrix updated according to 'confound'.

Examples


model <- make_model('X -> Y') %>%
  set_confound(list('X <-> Y'))
get_parameters(model)

# In this case we notionally place a distribution but in fact Y has degenerate support
make_model('X -> Y -> Z') %>%
  set_restrictions(c(increasing('X', 'Y')), keep = TRUE) %>%
  set_confound(list('X <-> Y')) %>%
  get_parameter_matrix()

# X nodes assigned conditional on Y
make_model('X -> Y') %>%
  set_confound(list(X = 'Y')) %>%
  get_parameter_matrix()

# Y nodes assigned conditional on X
make_model('X -> Y') %>%
  set_confound(list(Y = 'X')) %>%
  get_parameter_matrix()

model <- make_model('X -> Y') %>%
  set_confound(list(X = '(Y[X=1]>Y[X=0])', X = '(Y[X=1]<Y[X=0])', X = '(Y[X=1]==Y[X=0])'))

model <- make_model('X -> M -> Y') %>%
set_confound (list(X = '(Y[X=1]>Y[X=0])',
                 M = 'Y',
                 X = '(Y[X=1]<Y[X=0])'))

confound = list(A = '(D[A=., B=1, C=1]>D[A=., B=0, C=0])')
model <- make_model('A -> B -> C -> D; B -> D') %>%
 set_confound(confound = confound)

# Example where two parents are confounded
model <- make_model('A -> B <- C') %>%
  set_confound(list(A = 'C==1')) %>%
  set_parameters(c(0,1,1,0, .5, .5, rep(.0625, 16)))
cor(simulate_data(model, n = 20))

model <- make_model('X -> Y')
confound <- list(X = '(Y[X=1] > Y[X=0])', X = '(Y[X=1] == 1)')
model <- set_confound(model = model, confound = confound)

model <- make_model('X -> Y <- S; S -> W') %>%
  set_restrictions(c(
  increasing('X', 'Y'), increasing('S', 'W'),
  increasing('S', 'Y'), decreasing('S', 'Y')))
model1 <-  set_confound(model, list(X = 'S==1', S = 'W[S=1]==1'), add_confounds_df = TRUE)
model1$confounds_df
model2 <-  set_confound(model, list(S = 'X==1', S = 'W[S=1]==1'), add_confounds_df = TRUE)
model2$confounds_df


[Package CausalQueries version 0.0.3 Index]