QS Experiments / QS - Whats the best time to sleep?

Abstract

What did i do?

I've measured my sleep start time, sleep quality and quantity to find out what's my optimal bedtime.

How did i do it?

I've slept 145 nights with Dreem 2 headband and did a statistical analysis

What did i learn?

The later i'm going to sleep, the less total sleep time i'll get.
I've found my optimal sleep time around 21:30 - 22:30 and will stick to it.

Introduction

Going to bed at a right time seems to impact sleep quantity and quality according to recent scientific evidence. Current evidence indicate that about 7-8 hours of total sleep time (TST) is considered healthy optimal range for adults.
TST is a simply sum of Deep Sleep, Rem Sleep and Light Sleep.

The purpose of this observational data analysis (n=1) is to determine optimal sleep start time.

Materials & Methods

Participant

Adult male (n=1) with anthropometrics described below

Mean SD n
Age, y 34
Height, cm 184
Weight, kg 60.2 1.44 348
BMI, kg/m^2 17.7 0.42 348
Waist, cm 70.7 1.17 44
Hip, cm 86.1 1.13 44
Neck, cm 37 0.77 38
Wrist, cm 16.2 3

Weight was measured daily. Waist, hip and neck circumference - weekly. Wrist measure was not regular. n is number of measurements.

Experimental design

During 145 nights (from 2020-08-27 to 2021-08-21) sleep quality and quantity was assessed by Dreem 2 EEG Headband which was validated[1] against gold standard PSG.

Every sunday between 19:00 and 22:00 participant filled frequently used in research questionairres: General Anxiety Disorder (GAD-7), Center for Epidemiologic Studies Depression Scale (CES-D), Perceived Stress Scale (PSS), Fatigue Severity Scale (FSS), Insomnia Severity Index (ISI), Epworth Sleepiness Scale (ESS), Pittsburgh Sleep Quality Index (PSQI)

Everyday at the evening times between 19:00 and 22:00 Positive and Negative Affect Schedule (PANAS) was filled to asess PA and NA of the present day.

Every morning, within 10 minutes after waking up participant scored subjective sleep quality (SQ) on a 7-point Likert scale:
0 - Very poor,1 - Poor, 2 - Less than Avg, 3 - Average, 4 - Good, 5 - Excellent,6 - Perfect.

Mean SD Median IQR 95% CI for mean n
PA 29.1 3.71 30 [27,32] [28.6,29.5] 287
NA 9.8 2.07 9 [8,10] [9.5,10.0] 287
ESS 1.8 0.59 2 [1,2] [1.6,2.0] 41
GAD-7 4.1 1.48 4 [3,5] [3.7,4.5] 45
ISI 7.0 2.53 7 [5,9] [6.3,7.8] 45
PSS 10.4 2.94 10 [9,13] [9.5,11.3] 43
FSS 20.9 5.03 20 [17,24] [19.2,22.7] 35
PSQI 4.7 1.22 4 [4,6] [4.6,4.9] 33
SQ 3.29 0.91 3 [3,4] [3.2,3.4] 282

95% CI for mean was calculated using bootstrap percentile. PA, NA, SQ was assessed daily, everything else assessed weekly. IQR - interquantile range [Q1,Q3]

Results

The data summary shown below

TST = (DEEP + REM + LIGHT), SOL - sleep onset latency, WASO - time awake after sleep onset. StartTime, DEEP, REM, LIGHT, TST in hours, SOL in minutes

Linear regression

effect p-adjusted effect size
TST, h -0.56 0.0003* weak
DEEP, h 0.074 0.55 very weak
REM, h -0.06 0.69 very weak
SOL, m 2.83 0.69 very weak
WASO, h 0.03 0.51 very weak
Awakenings, count 0.17 0.69 very weak
Position Changes, count 0.96 0.69 very weak

We can see a slope of -0.56 hour (-33 minutes) in Total Sleep Time for each additional 1 hour of Sleep Start Time with weak effect size. Even with weak effect size, -33 minutes seems to be valuable change. 95% Confidence interval for slope is very narrow [-0.568,-0.551]. Other sleep characteristics didnt show significant results.

Total sleep time (TST), hours

StartTime - 24h format sleep start time.

Discussion

The main result of this experiment is a statistically significant assocation between sleep time schedule and total sleep time. Since DEEP & REM stages arent affected, decrease in TST might by due LIGHT sleep.
In conclusion, the later i'm going to sleep, the less total sleep time i'll get.
Plot points me to optimal sleep times between 21:30 to 22:00 which i'm going to follow, seems there is no side effects.

A limitations:

Data availability & Information

Welcome for questions, suggestions and critics in comments below.

Dreem 2 device unmodified data is fully available here and format is explained by manufacturer.

Data for questionaires will be presented soon.

R Code:

library(effectsize)
library(lubridate)
library(ggplot2)


ggplotRegression <- function (fit) {
 
  require(ggplot2)
 
  ggplot(fit$model, aes_string(x = names(fit$model)[2], y = names(fit$model)[1])) +
    geom_point() +
    stat_smooth(method = "lm", col = "red") +
    labs(title = paste("Adj R2 = ",signif(summary(fit)$adj.r.squared, 5),
                       "Intercept =",signif(fit$coef[[1]],5 ),
                       " Slope =",signif(fit$coef[[2]], 5),
                       " P =",signif(summary(fit)$coef[2,4], 5)))
}


dreem <- read.csv("https://blog.kto.to/uploads/dreem.csv", skip = 5, sep = ';', header = TRUE)
dreem <- dreem[!is.na(dreem$Type),]

starttime = vector(); stims = vector(); deeptime = vector(); remtime = vector(); waso = vector(); sol = vector(); lighttime = vector()
for (i in 1:nrow(dreem)) {
  sleepstart <- strsplit(dreem$Start.Time[i], "T")[[1]][2]
  sleepstarttime <- strsplit(sleepstart, "\\+")[[1]][1]
  starttime[i] <- period_to_seconds(hms(sleepstarttime))
  deeptime[i] <- period_to_seconds(hms(dreem$Deep.Sleep.Duration[i]))
  remtime[i] <- period_to_seconds(hms(dreem$REM.Duration[i]))
  lighttime[i] <- period_to_seconds(hms(dreem$Light.Sleep.Duration[i]))
  sol[i] <- period_to_seconds(hms(dreem$Sleep.Onset.Duration[i]))
  waso[i]  <- period_to_seconds(hms(dreem$Wake.After.Sleep.Onset.Duration[i]))
}
dreem$StartTime <- (starttime/3600)
dreem$DEEP <- (deeptime/3600)
dreem$REM <- (remtime/3600)
dreem$LIGHT <- (lighttime/3600)
dreem$TST <- (deeptime + remtime + lighttime)/3600
dreem$WASO <- (waso/3600)
dreem$SOL <- (sol/60)

l <- lm(cbind(TST, DEEP, REM, SOL, WASO, Number.of.awakenings, Position.Changes) ~ StartTime, data=dreem)
summary(dreem)
summary(anova(l))
s <- summary(l); s
interpret_r2(s$`Response TST`$adj.r.squared[1])
interpret_r2(s$`Response DEEP`$adj.r.squared[1])
interpret_r2(s$`Response REM`$adj.r.squared[1])
interpret_r2(s$`Response WASO`$adj.r.squared[1])
interpret_r2(s$`Response SOL`$adj.r.squared[1])
interpret_r2(s$`Response Number.of.awakenings`$adj.r.squared[1])
interpret_r2(s$`Response Position.Changes`$adj.r.squared[1])

p.adjust(c(
  s$`Response TST`$coefficients[,4][2],
  s$`Response DEEP`$coefficients[,4][2],
  s$`Response REM`$coefficients[,4][2],
  s$`Response WASO`$coefficients[,4][2],
  s$`Response SOL`$coefficients[,4][2],
  s$`Response Number.of.awakenings`$coefficients[,4][2],
  s$`Response Position.Changes`$coefficients[,4][2]), method="BH") #< 0.05
confint(lm(TST ~ StartTime, data=dreem), level = 0.05)

ggplotRegression(lm(cbind(dreem$TST) ~ dreem$StartTime, data=dreem))

Response TST :

Call:
lm(formula = TST ~ StartTime, data = dreem)

Residuals:
    Min      1Q  Median      3Q     Max
-2.6040 -0.3347  0.1767  0.4709  1.4574

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)  19.5134     2.9110   6.703 4.37e-10 ***
StartTime    -0.5601     0.1325  -4.228 4.19e-05 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.7744 on 143 degrees of freedom
Multiple R-squared:  0.1111,    Adjusted R-squared:  0.1049
F-statistic: 17.88 on 1 and 143 DF,  p-value: 4.187e-05


Response DEEP :

Call:
lm(formula = DEEP ~ StartTime, data = dreem)

Residuals:
     Min       1Q   Median       3Q      Max
-0.86080 -0.25705 -0.07327  0.21778  1.00792

Coefficients:
            Estimate Std. Error t value Pr(>|t|)  
(Intercept)  3.35478    1.36085   2.465   0.0149 *
StartTime   -0.07400    0.06193  -1.195   0.2341  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.362 on 143 degrees of freedom
Multiple R-squared:  0.009885,    Adjusted R-squared:  0.002961
F-statistic: 1.428 on 1 and 143 DF,  p-value: 0.2341


Response REM :

Call:
lm(formula = REM ~ StartTime, data = dreem)

Residuals:
     Min       1Q   Median       3Q      Max
-1.15452 -0.36894  0.00812  0.33504  1.38979

Coefficients:
            Estimate Std. Error t value Pr(>|t|)
(Intercept)  2.83648    1.98570   1.428    0.155
StartTime   -0.05841    0.09037  -0.646    0.519

Residual standard error: 0.5283 on 143 degrees of freedom
Multiple R-squared:  0.002913,    Adjusted R-squared:  -0.00406
F-statistic: 0.4178 on 1 and 143 DF,  p-value: 0.5191


Response SOL :

Call:
lm(formula = SOL ~ StartTime, data = dreem)

Residuals:
    Min      1Q  Median      3Q     Max
-15.576  -7.216  -2.670   4.163  61.907

Coefficients:
            Estimate Std. Error t value Pr(>|t|)
(Intercept)  -42.466     42.645  -0.996    0.321
StartTime      2.826      1.941   1.456    0.148

Residual standard error: 11.35 on 143 degrees of freedom
Multiple R-squared:  0.01461,    Adjusted R-squared:  0.007717
F-statistic:  2.12 on 1 and 143 DF,  p-value: 0.1476


Response WASO :

Call:
lm(formula = WASO ~ StartTime, data = dreem)

Residuals:
     Min       1Q   Median       3Q      Max
-0.47806 -0.23204 -0.11823  0.08589  1.76773

Coefficients:
            Estimate Std. Error t value Pr(>|t|)
(Intercept) -0.21103    1.41582  -0.149    0.882
StartTime    0.03066    0.06443   0.476    0.635

Residual standard error: 0.3767 on 143 degrees of freedom
Multiple R-squared:  0.001581,    Adjusted R-squared:  -0.005401
F-statistic: 0.2264 on 1 and 143 DF,  p-value: 0.6349


Response Number.of.awakenings :

Call:
lm(formula = Number.of.awakenings ~ StartTime, data = dreem)

Residuals:
    Min      1Q  Median      3Q     Max
-4.5554 -1.4558 -0.3744  1.6138  8.5154

Coefficients:
            Estimate Std. Error t value Pr(>|t|)
(Intercept)   1.5446     9.7739   0.158    0.875
StartTime     0.1742     0.4448   0.392    0.696

Residual standard error: 2.6 on 143 degrees of freedom
Multiple R-squared:  0.001072,    Adjusted R-squared:  -0.005914
F-statistic: 0.1535 on 1 and 143 DF,  p-value: 0.6958


Response Position.Changes :

Call:
lm(formula = Position.Changes ~ StartTime, data = dreem)

Residuals:
     Min       1Q   Median       3Q      Max
-16.5874  -4.2643  -0.2878   4.0179  16.9139

Coefficients:
            Estimate Std. Error t value Pr(>|t|)
(Intercept)   1.3390    25.2407   0.053    0.958
StartTime     0.9568     1.1487   0.833    0.406

Residual standard error: 6.715 on 143 degrees of freedom
Multiple R-squared:  0.004829,    Adjusted R-squared:  -0.002131
F-statistic: 0.6938 on 1 and 143 DF,  p-value: 0.4063

[1] 0.0002930587 0.5462725477 0.6958398243 0.6958398243 0.5165718622 0.6958398243 0.6958398243

Statistical analysis

RStudio version 1.3.959 and R version 4.0.2 was user for  a simple linear regression model and to calculate slopes and p-values.
P-adjusted is p-value adjusted for multiple comparisons by method of Benjamini, Hochberg, and Yekutieli.
Effect sizes based on adjusted R2, Cohen's 1988 rules

References

  1. Arnal PJ, Thorey V, Debellemaniere E, et al. The Dreem Headband compared to polysomnography for EEG signal acquisition and sleep staging. Sleep 2020. https://doi.org/10.1093/sleep/zsaa097