DeclareDesign

Really simple stepped wedge


#1

Someone asked me to draw up a stepped wedge design. Here’s a very basic setup with 3 periods and 6 individuals. Would be interesting to play around with parameters more to see where bias creeps in and how best to deal with it.

library(DeclareDesign)
library(tidyverse)

# tau is treatment effect
tau <- 1

# Population
pop <- declare_population(
  t = add_level(N = 3, u_t = rnorm(N)),
  i = add_level(N = 6, u_i = rnorm(N), nest = FALSE),
  obs = cross_levels(by = join(t, i), 
                     u_ti = rnorm(N)))
# Example
design <- pop + NULL
draw_data(design)

# Potential outcomes
pos <- declare_potential_outcomes(
  Y_Z_0 = u_i + u_t + u_ti,
  Y_Z_1 = u_i + u_t + u_ti + tau
)

design <- design + pos
draw_data(design)

# Assign individuals to be treated in a wave
assignment_to_wave <- declare_assignment(clusters = i, 
                                         conditions = 1:3, 
                                         assignment_variable = "wave")
# See ?randomizr::cluster_ra for more details on what cluster assignments 
# you can do
  
design <- design + assignment_to_wave
draw_data(design)

# Now make a function for if you're assigned in a given period
get_assignment_in_t <- declare_step(
  Z = as.numeric(t >= wave), 
  handler = fabricate
)

design <- design + get_assignment_in_t
draw_data(design)

# Now reveal outcomes 

reveal_Y <- declare_reveal(Y,Z)
design <- design + reveal_Y
draw_data(design)

# Add estimand 
estimand <- declare_estimand(ate = mean(Y_Z_1 - Y_Z_0))
design <- design + estimand
draw_estimands(design)

# Add estimator
estimator <- declare_estimator(Y ~ Z, model = lm_robust)
design <- design + estimator
draw_estimates(design)

# Summarize design
summary(design)

# Simulate design
simulate_design(design,sims = 50)

# Diagnose design
diagnose_design(design)

# Suppose effects are correlated with period
# Potential outcomes
pos_corr <- declare_potential_outcomes(
  Y_Z_0 = u_i + u_t + u_ti,
  Y_Z_1 = u_i + u_t + u_ti + tau * u_t
)
design_corr_period <- pop + pos_corr + assignment_to_wave + get_assignment_in_t +
  reveal_Y + estimand + estimator 

diagnose_design(design, design_corr_period)

#2

This looks pretty good - you may want to also include a baseline / t=0 timepoint, otherwise you have one cluster that never gets a control-group measurement. (I think)


#3

Great point. You’re absolutely right that one individual (cluster) will never have untreated measurements under this design. To make a baseline with three treatment waves you could use:

pop <- declare_population(
  t = add_level(N = 4, u_t = rnorm(N)),
  i = add_level(N = 6, u_i = rnorm(N), nest = FALSE),
  obs = cross_levels(by = join(t, i), 
                     u_ti = rnorm(N)))
assignment_to_wave <- declare_assignment(clusters = i, 
                                         conditions = 2:4, 
                                         assignment_variable = "wave")