I've measured my caffeine intake, sleep quality and quantity to find out is there a safe dose, which not disrupt my sleep.
I've slept 145 nights with Dreem 2 headband and measure my daily caffeine intake.
Caffeine is a widely consumed stimulant which in most cases disrupt sleep quantity and quality.
The purpose of this observational data analysis (n=1) is to determine impact of caffeine on my sleep.
1 adult male anthropometrics was described in previous article
During 145 nights (from 2020-08-27 to 2021-08-21) amount of pink noise stimulations and DEEP sleep length was assessed by Dreem 2 EEG Headband which was validated[1] against gold standard PSG. At same time, all food and fluid intake was carefully logged and caffeine intake extracted from dietary log. Caffeine amount in each product was determined from a popular online food database - https://nutritiondata.self.com/
Subjective sleep quality, mood, depression, anxiety, stress, fatigue and sleepiness was assessed by a popular in scientific research questionnaires described in previous experiment
Sleep metrics was described in previous article.
Caffeine intake visual inspection:
Linear regression, Caffeine intake, mg
effect | p-adjusted | effect size | |
TST, m | -0.402 | 0.00001* | moderate |
DEEP, m | -0.104 | 0.0105* | weak |
REM, m | -0.203 | 0.0007* | weak |
AWAKE, m | 0.056 | 0.484 | very weak |
Awakenings, count | -0.005 | 0.362 | very weak |
Sleep efficacy | -0.027 | 0.01 | weak |
With my average 68mg caffeine intake per day i'll get
Total sleep time (TST), minutes
Caffeine in mg. Total Sleep Time (DEEP + REM + LIGHT) in minutes
Confidence interval for TST is pretty narrow [-0.407,-0.396] and have a moderate effect size.
Even at low doses caffeine worsens my sleep in restorative sleep phases.
But daytime of caffeine intake also matters, maybe i've consumed it in evening?
Usually my caffeine consumed between 8:30 and 11:00. Sometimes its a bit late, but most of it consumed before 13:30.
The main result of this experiment is a statistically significant negative effect of caffeine on my sleep.
Plot points me to lower caffeine intake to 30mg and strict intake schedule to 8:30 - 10:00.
There is a few SNP's in DNA which may cause this, but that's not the case - since i've did x30 whole genome sequence and didn't found anything.
A limitations:
Welcome for questions, suggestions and critics in comments below.
Dreem 2 device unmodified data is fully available here and format is explained by manufacturer. Caffeine intake data available here.
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)))
}
caffeine <- read.csv("https://blog.kto.to/uploads/caffeine.csv")
caffeine$`caffeine`[is.na(caffeine$`caffeine`)] <- 0;
dreem <- read.csv("https://blog.kto.to/uploads/dreem.csv", skip = 5, sep = ';', header = TRUE)
dreem <- dreem[!is.na(dreem$Type),]
row.names(dreem) <- NULL
results = vector();
for (i in 1:nrow(dreem))
{
sleepstart <- strsplit(dreem$Start.Time[i], "T")[[1]][2]
sleepstartdate <- strsplit(dreem$Start.Time[i], "T")[[1]][1]
for(j in 1:nrow(caffeine))
{
sleepstarttime <- strsplit(sleepstart, "\\+")[[1]][1]
if(as.Date(caffeine$datetime[j]) == as.Date(sleepstartdate))
{
results <- append(results, c(
starttime = period_to_seconds(hms(sleepstarttime))/60,
deep = period_to_seconds(hms(dreem$Deep.Sleep.Duration[i]))/60,
rem = period_to_seconds(hms(dreem$REM.Duration[i]))/60,
light = period_to_seconds(hms(dreem$Light.Sleep.Duration[i]))/60,
tst = (period_to_seconds(hms(dreem$Deep.Sleep.Duration[i])) + period_to_seconds(hms(dreem$REM.Duration[i])) + period_to_seconds(hms(dreem$Light.Sleep.Duration[i])))/60,
sol = period_to_seconds(hms(dreem$Sleep.Onset.Duration[i]))/60,
waso = period_to_seconds(hms(dreem$Wake.After.Sleep.Onset.Duration[i]))/60,
awakes = dreem$Number.of.awakenings[i],
awake = period_to_seconds(hms(dreem$Wake.After.Sleep.Onset.Duration[i]))/60 + period_to_seconds(hms(dreem$Wake.After.Sleep.Onset.Duration[i]))/60,
positions = dreem$Position.Changes[i],
eff = dreem$Sleep.efficiency[i],
caffeine = caffeine$caffeine[j]
))
}
}
}
res_li <- split(unname(results),names(results));
summary(res_li)
summary(caffeine)
l <- lm(cbind(deep, rem, tst, awake, awakes, eff) ~ caffeine, data=res_li)
summary(anova(l))
s <- summary(l); s
p.adjust(c(
s$`Response deep`$coefficients[,4][2],
s$`Response rem`$coefficients[,4][2],
s$`Response tst`$coefficients[,4][2],
s$`Response awake`$coefficients[,4][2],
s$`Response awakes`$coefficients[,4][2],
s$`Response eff`$coefficients[,4][2]), method="BH") #< 0.05
interpret_r2(s$`Response deep`$adj.r.squared[1], rules = "cohen1988")
interpret_r2(s$`Response rem`$adj.r.squared[1], rules = "cohen1988")
interpret_r2(s$`Response tst`$adj.r.squared[1], rules = "cohen1988")
interpret_r2(s$`Response awake`$adj.r.squared[1], rules = "cohen1988")
interpret_r2(s$`Response awakes`$adj.r.squared[1], rules = "cohen1988")
interpret_r2(s$`Response eff`$adj.r.squared[1], rules = "cohen1988")
lpa <- lm(tst ~ caffeine, data=res_li);
confint(lpa, level = 0.05)
ggplotRegression(lpa)
Response deep :
Call:
lm(formula = deep ~ caffeine, data = res_li)
Residuals:
Min 1Q Median 3Q Max
-52.952 -14.231 -2.675 13.256 58.341
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 110.84743 3.13984 35.304 < 2e-16 ***
caffeine -0.10375 0.03793 -2.735 0.00702 **
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 21.28 on 143 degrees of freedom
Multiple R-squared: 0.04972, Adjusted R-squared: 0.04308
F-statistic: 7.483 on 1 and 143 DF, p-value: 0.007019
Response rem :
Call:
lm(formula = rem ~ caffeine, data = res_li)
Residuals:
Min 1Q Median 3Q Max
-76.093 -21.769 2.958 21.458 77.432
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 107.12047 4.46661 23.982 < 2e-16 ***
caffeine -0.20344 0.05396 -3.771 0.000238 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 30.27 on 143 degrees of freedom
Multiple R-squared: 0.09043, Adjusted R-squared: 0.08407
F-statistic: 14.22 on 1 and 143 DF, p-value: 0.0002377
Response tst :
Call:
lm(formula = tst ~ caffeine, data = res_li)
Residuals:
Min 1Q Median 3Q Max
-191.034 -23.352 6.892 34.466 78.473
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 460.03973 6.71817 68.477 < 2e-16 ***
caffeine -0.40197 0.08115 -4.953 2.03e-06 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 45.53 on 143 degrees of freedom
Multiple R-squared: 0.1464, Adjusted R-squared: 0.1405
F-statistic: 24.54 on 1 and 143 DF, p-value: 2.031e-06
Response awake :
Call:
lm(formula = awake ~ caffeine, data = res_li)
Residuals:
Min 1Q Median 3Q Max
-53.57 -27.70 -16.39 11.32 212.65
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 51.64242 6.66267 7.751 1.55e-12 ***
caffeine 0.05643 0.08048 0.701 0.484
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 45.16 on 143 degrees of freedom
Multiple R-squared: 0.003426, Adjusted R-squared: -0.003543
F-statistic: 0.4915 on 1 and 143 DF, p-value: 0.4844
Response awakes :
Call:
lm(formula = awakes ~ caffeine, data = res_li)
Residuals:
Min 1Q Median 3Q Max
-4.5095 -1.6467 -0.4457 1.4251 8.7842
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 5.699684 0.382420 14.904 <2e-16 ***
caffeine -0.004783 0.004619 -1.035 0.302
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 2.592 on 143 degrees of freedom
Multiple R-squared: 0.007441, Adjusted R-squared: 0.0004997
F-statistic: 1.072 on 1 and 143 DF, p-value: 0.3022
Response eff :
Call:
lm(formula = eff ~ caffeine, data = res_li)
Residuals:
Min 1Q Median 3Q Max
-23.144 -3.054 1.746 3.583 9.172
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 90.583341 0.813813 111.307 < 2e-16 ***
caffeine -0.027474 0.009831 -2.795 0.00591 **
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 5.516 on 143 degrees of freedom
Multiple R-squared: 0.05179, Adjusted R-squared: 0.04516
F-statistic: 7.81 on 1 and 143 DF, p-value: 0.005908
caffeine caffeine caffeine caffeine caffeine caffeine
1.052829e-02 7.130307e-04 1.218435e-05 4.843764e-01 3.626927e-01 1.052829e-02
> interpret_r2(s$`Response deep`$adj.r.squared[1], rules = "cohen1988")
[1] "weak"
(Rules: cohen1988)
> interpret_r2(s$`Response rem`$adj.r.squared[1], rules = "cohen1988")
[1] "weak"
(Rules: cohen1988)
> interpret_r2(s$`Response tst`$adj.r.squared[1], rules = "cohen1988")
[1] "moderate"
(Rules: cohen1988)
> interpret_r2(s$`Response awake`$adj.r.squared[1], rules = "cohen1988")
[1] "very weak"
(Rules: cohen1988)
> interpret_r2(s$`Response awakes`$adj.r.squared[1], rules = "cohen1988")
[1] "very weak"
(Rules: cohen1988)
> interpret_r2(s$`Response eff`$adj.r.squared[1], rules = "cohen1988")
[1] "weak"
(Rules: cohen1988)
> confint(lpa, level = 0.05)
47.5 % 52.5 %
(Intercept) 459.6177100 460.4617401
caffeine -0.4070717 -0.3968761
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