Skip to content

Causal consistency #24

@cegepi

Description

@cegepi

Hello,

I have been following along with the vignette "simcausal Package: Technical Details and Extended Examples of Simulations with Complex
Longitudinal Data". I've noticed that, even with the same random seed, the observed data generated from a DAG do not have the same simulated outcomes as the corresponding counterfactual DAGs, at the level of the observed treatment. By consistency, the observed outcome at factual treatment level A=1 should be the potential outcome for a=1.

library("simcausal")

Setting up the DAG

D <- DAG.empty() #start with DAG.empty
D <- D + # then add nodes
node("race",
distr = "rcat.b1",
probs = c(0.5, 0.25, 0.25)) +
node("W1",
distr = "rnorm",
mean = ifelse(race == 1, 0, ifelse(race == 2, 3, 10)),
sd = 1) +
node("W2",
distr = "runif",
min = 0, max = 1) +
node("W3",
distr = "rbern",
prob = plogis(-0.5 + 0.7 * W1 + 0.3 * W2)) +
node("Anode",
distr = "rbern",
prob = plogis(-0.5 - 0.3 * W1 - 0.3 * W2 - 0.2 * W3)) +
node("Y",
distr = "rbern",
prob = plogis(-0.1 + 1.2 * Anode + 0.1 * W1 + 0.3 * W2 + 0.2 * W3))
Dset <- set.DAG(D) #use set.DAG to finalize or "lock in" the DAG

Simulating Observed Data

Odat <- sim(DAG = Dset, n = 1000, rndseed = 123)

Simulating Counterfactual Data

Treatment intervention: make everyone treated

A1 <- node("Anode", distr = "rbern", prob = 1)
Dset <- Dset + action("A1", nodes = A1)

Treatment intervention: make everyone untreated

A0 <- node("Anode", distr = "rbern", prob = 0)
Dset <- Dset + action("A0", nodes = A0)

Generating the counterfactual data from the DAG actions

Xdat1 <- sim(DAG = Dset, actions = c("A1", "A0"), n = 1000, rndseed = 123)

exposed_data <- Xdat1[["A1"]]
exposed_data <- exposed_data %>%
rename(treated = Anode,
Y_if_treated=Y)

unexposed_data <- Xdat1[["A0"]]

unexposed_data <- unexposed_data %>%
rename(untreated = Anode,
Y_if_untreated=Y) %>%
dplyr::select(ID, untreated, Y_if_untreated)

both_potential_outcomes <- exposed_data %>%
left_join(unexposed_data, by = "ID") %>%
select(-treated, -untreated)

Showing that lack of causal consistency. The Y in the observed dataset for untreated people should be the same as the counterfactual Y under no treatment. Cross-tab shows very different Y observed and Y counterfactual.

counterfactuals <- both_potential_outcomes %>%
select(ID, Y_if_treated, Y_if_untreated)

test <- Odat %>%
left_join(counterfactuals, by="ID")

test %>%
filter(Anode==0) %>%
with(table(Y,Y_if_untreated))

Image

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions