This figure accompanies the paper: Self-reported sleep health is more than a combination of multiple objective sleep measures. Each graph displays the cube at the constant median value for the listed sleep dimension.

Cubes at Median values

Midpoint 2am

This cube is shown in Figure 2.

Duration 7 hours

Regularity 1 hour

Efficiency 80%

Cube R Code

# linear model for cube visualization 
fit_cube <- lm(RU_SATED_c ~ 
                 # linear terms
                 duration + regularity  + efficiency + midpoint +
                 # 2 way interactions 
                 midpoint*duration + regularity*duration + midpoint*regularity + 
                    efficiency*duration + efficiency*midpoint + efficiency*regularity +
                 # 3 way interactions 
                 midpoint*(regularity)*duration +
                   midpoint*(efficiency)*duration + 
                   midpoint*(efficiency)*regularity + 
                   duration*(efficiency)*regularity + 
                 # 4 way interaction
                 duration*(efficiency)*regularity*(midpoint) +
                 # quadratic terms
                 I(midpoint^2) + I(regularity^2) + I(duration^2) +  I(efficiency^2), 
               data = snb_ru_sated)
#### Example cube code for midpoint @ 2am (-1) ##############

## Make sequence of possible duration, efficiency, and regularity (we used approx 2.5th and 97.5th percentile as cutoffs)
### duration and regularity are sequenced by 0.5 hours and se is sequenced by 5%
dur_seq <-  data.frame(seq(4.5, 10, by = 0.5))
se_seq <-  data.frame(seq(65, 90, by = 5))
reg_seq <-  data.frame(seq(-3.5, 0, by = 0.5))
## Set constant value for midpoint
mid_const <- -1

# join all sequences together to have a row for each unique combination 
seq_dat <- cross_join(dur_seq,se_seq) %>% 
  cross_join(reg_seq) %>% 
  mutate(midpoint= mid_const) %>%
  #rename variables to match our variable names
  dplyr::rename(duration = `seq.4.5..10..by...0.5.`,
         efficiency = `seq.65..90..by...5.`,
         regularity = `seq..3.5..0..by...0.5.`)

# predict Ru-SATED values across sequence combinations based on our model from above (fit_cube) 
seq_dat$rusated_pred <- predict(fit_cube, new = seq_dat)

# use plotly package to plot data in 3D with color
cube_plot <- plot_ly(data = seq_dat, 
        #call data for x, y and z axis
        x=seq_dat$efficiency, y=seq_dat$duration, z=seq_dat$regularity,
        #visualization settings
        type="scatter3d", mode="markers", alpha = 1, alpha_stroke = 1, 
        #set color to predicted Ru-SATED values
        color =seq_dat$rusated_pred, 
        #set color min and max to  min and max of predicted values
        marker = list(cmin = 12, cmax = 17))%>%
  #add title, axis title, and legend title
  layout(
    title = 'Midpoint 2am',     
    scene = list(xaxis = list(title = 'Efficiency'),
                 yaxis = list(title = 'Duration (Hrs)'),
                 zaxis = list(title = 'Regularity')),
          annotations = list(
                        x = 1.13,
                        y = 1.05,
                        text = 'Ru-SATEDc',
                        xref = 'paper',
                        yref = 'paper',
                        showarrow = FALSE))