This code created the longitudinal dataset used by other analysis.
The code creates:

Data creation is performed using the package ‘simcausal’.

Firstly, we define the relationship between variables:

D <- DAG.empty() + 
  node("ba", distr="rnorm", mean=0, sd = 1) +
  node("bb", distr="rnorm", mean=0, sd = 1) +
  node("bc", distr="rnorm", mean=0, sd = 1) +
  
  node("u", t=0, distr="rnorm", mean=0, sd = 1) +
  node("c", t=0, distr="rbern", prob=0) +
  node("l", t=0, distr="rbern", prob=plogis(-2 + 1.5*u[t] + 0.1*ba - 0.1*bb + 0.1*bc)) + 
  node("a", t=0, distr="rbern", prob=plogis(-2 + 1.5*l[t] + 0.2*ba - 0.2*bb + 0.2*bc)) +
  
  node("u", t=1:4, distr="rnorm", mean=0.7*u[t-1], sd = 1) +
  node("c", t=1:4, distr="rbern", prob=ifelse(c[t-1]==1,1,plogis(-4.75 + 2.0*a[t-1] + 2.0*l[t-1]))) +
  node("l", t=1:4, distr="rbern", prob=ifelse(c[t]==1,NA,plogis(-2 + 1.0*a[t-1] + 2.0*l[t-1] + 1.5*u[t] + 0.1*ba - 0.1*bb + 0.1*bc))) +
  node("a", t=1:4, distr="rbern", prob=ifelse(c[t]==1,NA,plogis(-2 + 2.0*a[t-1] + 1.5*l[t] + 0.2*ba - 0.2*bb + 0.2*bc))) +
  
  node("y", t=0, distr="rnorm", mean=(1.00*a[t]
                                      + 0.50*l[t]
                                      + 0.50*u[t]
                                      + 0.2*ba - 0.2*bb + 0.2*bc), sd=1) +
  node("y", t=1, distr="rnorm", mean=ifelse(c[t]==1,NA,(0.80*a[t-1] + 1.00*a[t]
                                                        + 0.50*l[t-1] + 0.50*l[t]
                                                        + 0.50*u[t-1] + 0.50*u[t]
                                                        + 0.2*ba - 0.2*bb + 0.2*bc)), sd=1) +
  node("y", t=2, distr="rnorm", mean=ifelse(c[t]==1,NA,(0.60*a[t-2] + 0.80*a[t-1] + 1.00*a[t]
                                                        + 0.50*l[t-2] + 0.50*l[t-1] + 0.50*l[t]
                                                        + 0.50*u[t-2] + 0.50*u[t-1] + 0.50*u[t]
                                                        + 0.2*ba - 0.2*bb + 0.2*bc)), sd=1) +
  node("y", t=3, distr="rnorm", mean=ifelse(c[t]==1,NA,(0.40*a[t-3] + 0.60*a[t-2] + 0.80*a[t-1] + 1.00*a[t]
                                                        + 0.50*l[t-3] + 0.50*l[t-2] + 0.50*l[t-1] + 0.50*l[t]
                                                        + 0.50*u[t-3] + 0.50*u[t-2] + 0.50*u[t-1] + 0.50*u[t]
                                                        + 0.2*ba - 0.2*bb + 0.2*bc)), sd=1) +
  node("y", t=4, distr="rnorm", mean=ifelse(c[t]==1,NA,(0.20*a[t-4] + 0.40*a[t-3] + 0.60*a[t-2] + 0.80*a[t-1] + 1.00*a[t]
                                                        + 0.50*l[t-4] + 0.50*l[t-3] + 0.50*l[t-2] + 0.50*l[t-1] + 0.50*l[t]
                                                        + 0.50*u[t-4] + 0.50*u[t-3] + 0.50*u[t-2] + 0.50*u[t-1] + 0.50*u[t]
                                                        + 0.2*ba - 0.2*bb + 0.2*bc)), sd=1)

Next, we set this causal structure, defining all ‘u’ variables as latent (so they will not be included in the final data)

D <- suppressWarnings(set.DAG(D, latent.v = c("u_0","u_1","u_2","u_3","u_4")))
...automatically assigning order attribute to some nodes...
node ba, order:1
node bb, order:2
node bc, order:3
node u_0, order:4
node c_0, order:5
node l_0, order:6
node a_0, order:7
node y_0, order:8
node u_1, order:9
node c_1, order:10
node l_1, order:11
node a_1, order:12
node y_1, order:13
node u_2, order:14
node c_2, order:15
node l_2, order:16
node a_2, order:17
node y_2, order:18
node u_3, order:19
node c_3, order:20
node l_3, order:21
node a_3, order:22
node y_3, order:23
node u_4, order:24
node c_4, order:25
node l_4, order:26
node a_4, order:27
node y_4, order:28

Finally, we create a dataset of 1000 observations, using the relationships defined in the previous steps. Note that, with this pattern of data, observations are deliberately missing when censoring occurs. However, ‘simcausal’ returns a warning when data is created as missing. In this case, that warning has been suppressed using the command ‘suppressWarnings’.

ldata <- suppressWarnings(simcausal::sim(D,n=1000))
simulating observed dataset from the DAG object

Censoring

Finally, we convert the binary (numeric) censoring variable to the form used by ‘ltmle’, using the function ‘BinaryToCensoring’.

# Convert numeric censoring variables to 'censored' variable for ltmle
ldata$c_0 <- BinaryToCensoring(is.censored=ldata$c_0)
ldata$c_1 <- BinaryToCensoring(is.censored=ldata$c_1)
ldata$c_2 <- BinaryToCensoring(is.censored=ldata$c_2)
ldata$c_3 <- BinaryToCensoring(is.censored=ldata$c_3)
ldata$c_4 <- BinaryToCensoring(is.censored=ldata$c_4)
LS0tDQp0aXRsZTogIkRhdGEgQ3JlYXRpb24iDQpkYXRlOiAiMyBEZWNlbWJlciAyMDE4Ig0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpDQpjbG91ZHN0b3IgPC0gIkM6L1VzZXJzL3ozMzEyOTExL0Nsb3Vkc3Rvci8iDQoubGliUGF0aHMocGFzdGUwKGNsb3Vkc3RvciwiUiBMaWJyYXJ5IikpDQoNCmxpYnJhcnkoInRtbGUiKQ0KbGlicmFyeSgibHRtbGUiKQ0KbGlicmFyeSgiU3VwZXJMZWFybmVyIikNCmxpYnJhcnkoInNpbWNhdXNhbCIpDQpsaWJyYXJ5KCJNQVNTIikNCmxpYnJhcnkoInJhbmdlciIpDQpsaWJyYXJ5KCJwYXJhbGxlbCIpDQpsaWJyYXJ5KCJkb1BhcmFsbGVsIikNCmxpYnJhcnkoImZvcmVhY2giKQ0KbGlicmFyeSgibG1lNCIpDQoNClJOR2tpbmQoa2luZD0iZGVmYXVsdCIsbm9ybWFsLmtpbmQ9ImRlZmF1bHQiKQ0Kc2V0LnNlZWQoNDMyMzYpDQpgYGANCg0KVGhpcyBjb2RlIGNyZWF0ZWQgdGhlIGxvbmdpdHVkaW5hbCBkYXRhc2V0IHVzZWQgYnkgb3RoZXIgYW5hbHlzaXMuICANClRoZSBjb2RlIGNyZWF0ZXM6DQoNCiogMyB6LWRpc3RyaWJ1dGVkIGJhc2VsaW5lICh0aW1lLWNvbnN0YW50KSB2YXJpYWJsZXMgKGJhLCBiYiwgYmMpLg0KKiBhIG5vcm1hbGx5IGRpc3RydXRlZCAnbGF0ZW50JyB2YXJpYWJsZSwgdV90LCBpbml0aWFsaXNlZCBhdCB0aW1lIDAgYW5kIHRoZW4gdXBkYXRlZCBhdCB0aW1lIHQ9MTo0Lg0KKiBhIGNvbmZvdW5kZXIgJ2wnIGJhc2VkIG9uIGJhc2VsaW5lIGNvdmFyaWF0ZXMgYW5kICd1JywgaW5pdGlhbGlzZWQgYXQgdGltZSAwIGFuZCB0aGVuIHVwZGF0ZWQgYXQgdGltZSB0PTE6NC4NCiogYW4gZXhwb3N1cmUgdmFyaWFibGUgYmFzZWQgb24gYmFzZWxpbmUgY292YXJpYXRlcyBhbmQgaW5pdGlhbCAnbCcsIGluaXRpYWxpc2VkIGF0IHRpbWUgMCBhbmQgdGhlbiB1cGRhdGVkIGF0IHRpbWUgdD0xOjQuDQoqIHkgdmFyaWFibGVzIGZvciBlYWNoIHQsIGJhc2VkIG9uIEFMTCB1LGwsYSAncHJpb3InIHRvIHRoYXQgeS4NCg0KRGF0YSBjcmVhdGlvbiBpcyBwZXJmb3JtZWQgdXNpbmcgdGhlIHBhY2thZ2UgJ3NpbWNhdXNhbCcuDQoNCkZpcnN0bHksIHdlIGRlZmluZSB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gdmFyaWFibGVzOg0KDQpgYGB7ciBkYWd9DQoNCkQgPC0gREFHLmVtcHR5KCkgKyANCiAgbm9kZSgiYmEiLCBkaXN0cj0icm5vcm0iLCBtZWFuPTAsIHNkID0gMSkgKw0KICBub2RlKCJiYiIsIGRpc3RyPSJybm9ybSIsIG1lYW49MCwgc2QgPSAxKSArDQogIG5vZGUoImJjIiwgZGlzdHI9InJub3JtIiwgbWVhbj0wLCBzZCA9IDEpICsNCiAgDQogIG5vZGUoInUiLCB0PTAsIGRpc3RyPSJybm9ybSIsIG1lYW49MCwgc2QgPSAxKSArDQogIG5vZGUoImMiLCB0PTAsIGRpc3RyPSJyYmVybiIsIHByb2I9MCkgKw0KICBub2RlKCJsIiwgdD0wLCBkaXN0cj0icmJlcm4iLCBwcm9iPXBsb2dpcygtMiArIDEuNSp1W3RdICsgMC4xKmJhIC0gMC4xKmJiICsgMC4xKmJjKSkgKyANCiAgbm9kZSgiYSIsIHQ9MCwgZGlzdHI9InJiZXJuIiwgcHJvYj1wbG9naXMoLTIgKyAxLjUqbFt0XSArIDAuMipiYSAtIDAuMipiYiArIDAuMipiYykpICsNCiAgDQogIG5vZGUoInUiLCB0PTE6NCwgZGlzdHI9InJub3JtIiwgbWVhbj0wLjcqdVt0LTFdLCBzZCA9IDEpICsNCiAgbm9kZSgiYyIsIHQ9MTo0LCBkaXN0cj0icmJlcm4iLCBwcm9iPWlmZWxzZShjW3QtMV09PTEsMSxwbG9naXMoLTQuNzUgKyAyLjAqYVt0LTFdICsgMi4wKmxbdC0xXSkpKSArDQogIG5vZGUoImwiLCB0PTE6NCwgZGlzdHI9InJiZXJuIiwgcHJvYj1pZmVsc2UoY1t0XT09MSxOQSxwbG9naXMoLTIgKyAxLjAqYVt0LTFdICsgMi4wKmxbdC0xXSArIDEuNSp1W3RdICsgMC4xKmJhIC0gMC4xKmJiICsgMC4xKmJjKSkpICsNCiAgbm9kZSgiYSIsIHQ9MTo0LCBkaXN0cj0icmJlcm4iLCBwcm9iPWlmZWxzZShjW3RdPT0xLE5BLHBsb2dpcygtMiArIDIuMCphW3QtMV0gKyAxLjUqbFt0XSArIDAuMipiYSAtIDAuMipiYiArIDAuMipiYykpKSArDQogIA0KICBub2RlKCJ5IiwgdD0wLCBkaXN0cj0icm5vcm0iLCBtZWFuPSgxLjAwKmFbdF0NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKyAwLjUwKmxbdF0NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKyAwLjUwKnVbdF0NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKyAwLjIqYmEgLSAwLjIqYmIgKyAwLjIqYmMpLCBzZD0xKSArDQogIG5vZGUoInkiLCB0PTEsIGRpc3RyPSJybm9ybSIsIG1lYW49aWZlbHNlKGNbdF09PTEsTkEsKDAuODAqYVt0LTFdICsgMS4wMCphW3RdDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICsgMC41MCpsW3QtMV0gKyAwLjUwKmxbdF0NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKyAwLjUwKnVbdC0xXSArIDAuNTAqdVt0XQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICArIDAuMipiYSAtIDAuMipiYiArIDAuMipiYykpLCBzZD0xKSArDQogIG5vZGUoInkiLCB0PTIsIGRpc3RyPSJybm9ybSIsIG1lYW49aWZlbHNlKGNbdF09PTEsTkEsKDAuNjAqYVt0LTJdICsgMC44MCphW3QtMV0gKyAxLjAwKmFbdF0NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKyAwLjUwKmxbdC0yXSArIDAuNTAqbFt0LTFdICsgMC41MCpsW3RdDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICsgMC41MCp1W3QtMl0gKyAwLjUwKnVbdC0xXSArIDAuNTAqdVt0XQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICArIDAuMipiYSAtIDAuMipiYiArIDAuMipiYykpLCBzZD0xKSArDQogIG5vZGUoInkiLCB0PTMsIGRpc3RyPSJybm9ybSIsIG1lYW49aWZlbHNlKGNbdF09PTEsTkEsKDAuNDAqYVt0LTNdICsgMC42MCphW3QtMl0gKyAwLjgwKmFbdC0xXSArIDEuMDAqYVt0XQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICArIDAuNTAqbFt0LTNdICsgMC41MCpsW3QtMl0gKyAwLjUwKmxbdC0xXSArIDAuNTAqbFt0XQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICArIDAuNTAqdVt0LTNdICsgMC41MCp1W3QtMl0gKyAwLjUwKnVbdC0xXSArIDAuNTAqdVt0XQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICArIDAuMipiYSAtIDAuMipiYiArIDAuMipiYykpLCBzZD0xKSArDQogIG5vZGUoInkiLCB0PTQsIGRpc3RyPSJybm9ybSIsIG1lYW49aWZlbHNlKGNbdF09PTEsTkEsKDAuMjAqYVt0LTRdICsgMC40MCphW3QtM10gKyAwLjYwKmFbdC0yXSArIDAuODAqYVt0LTFdICsgMS4wMCphW3RdDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICsgMC41MCpsW3QtNF0gKyAwLjUwKmxbdC0zXSArIDAuNTAqbFt0LTJdICsgMC41MCpsW3QtMV0gKyAwLjUwKmxbdF0NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKyAwLjUwKnVbdC00XSArIDAuNTAqdVt0LTNdICsgMC41MCp1W3QtMl0gKyAwLjUwKnVbdC0xXSArIDAuNTAqdVt0XQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICArIDAuMipiYSAtIDAuMipiYiArIDAuMipiYykpLCBzZD0xKQ0KYGBgDQoNCk5leHQsIHdlIHNldCB0aGlzIGNhdXNhbCBzdHJ1Y3R1cmUsIGRlZmluaW5nIGFsbCAndScgdmFyaWFibGVzIGFzIGxhdGVudCAoc28gdGhleSB3aWxsIG5vdCBiZSBpbmNsdWRlZCBpbiB0aGUgZmluYWwgZGF0YSkNCg0KYGBge3IgZGVmaW5lfQ0KRCA8LSBzdXBwcmVzc1dhcm5pbmdzKHNldC5EQUcoRCwgbGF0ZW50LnYgPSBjKCJ1XzAiLCJ1XzEiLCJ1XzIiLCJ1XzMiLCJ1XzQiKSkpDQpgYGANCg0KRmluYWxseSwgd2UgY3JlYXRlIGEgZGF0YXNldCBvZiAxMDAwIG9ic2VydmF0aW9ucywgdXNpbmcgdGhlIHJlbGF0aW9uc2hpcHMgZGVmaW5lZCBpbiB0aGUgcHJldmlvdXMgc3RlcHMuDQpOb3RlIHRoYXQsIHdpdGggdGhpcyBwYXR0ZXJuIG9mIGRhdGEsIG9ic2VydmF0aW9ucyBhcmUgZGVsaWJlcmF0ZWx5IG1pc3Npbmcgd2hlbiBjZW5zb3Jpbmcgb2NjdXJzLiBIb3dldmVyLCAnc2ltY2F1c2FsJyByZXR1cm5zIGEgd2FybmluZyB3aGVuIGRhdGEgaXMgY3JlYXRlZCBhcyBtaXNzaW5nLiBJbiB0aGlzIGNhc2UsIHRoYXQgd2FybmluZyBoYXMgYmVlbiBzdXBwcmVzc2VkIHVzaW5nIHRoZSBjb21tYW5kICdzdXBwcmVzc1dhcm5pbmdzJy4NCg0KYGBge3IgZGF0YX0NCmxkYXRhIDwtIHN1cHByZXNzV2FybmluZ3Moc2ltY2F1c2FsOjpzaW0oRCxuPTEwMDApKQ0KYGBgDQoNCiMjIENlbnNvcmluZw0KDQpGaW5hbGx5LCB3ZSBjb252ZXJ0IHRoZSBiaW5hcnkgKG51bWVyaWMpIGNlbnNvcmluZyB2YXJpYWJsZSB0byB0aGUgZm9ybSB1c2VkIGJ5ICdsdG1sZScsIHVzaW5nIHRoZSBmdW5jdGlvbiAnQmluYXJ5VG9DZW5zb3JpbmcnLg0KDQpgYGB7ciBjZW5zb3J9DQojIENvbnZlcnQgbnVtZXJpYyBjZW5zb3JpbmcgdmFyaWFibGVzIHRvICdjZW5zb3JlZCcgdmFyaWFibGUgZm9yIGx0bWxlDQpsZGF0YSRjXzAgPC0gQmluYXJ5VG9DZW5zb3JpbmcoaXMuY2Vuc29yZWQ9bGRhdGEkY18wKQ0KbGRhdGEkY18xIDwtIEJpbmFyeVRvQ2Vuc29yaW5nKGlzLmNlbnNvcmVkPWxkYXRhJGNfMSkNCmxkYXRhJGNfMiA8LSBCaW5hcnlUb0NlbnNvcmluZyhpcy5jZW5zb3JlZD1sZGF0YSRjXzIpDQpsZGF0YSRjXzMgPC0gQmluYXJ5VG9DZW5zb3JpbmcoaXMuY2Vuc29yZWQ9bGRhdGEkY18zKQ0KbGRhdGEkY180IDwtIEJpbmFyeVRvQ2Vuc29yaW5nKGlzLmNlbnNvcmVkPWxkYXRhJGNfNCkNCmBgYA0KDQoNCg==