# ZMA Sleep Experiment

A randomized blinded self-experiment of the effects of ZMA (zinc+magnesium+vitamin B6) on my sleep (experiments, biology, statistics, Zeo, R)
created: 13 March 2017; modified: 19 Feb 2018; status: in progress; confidence: possible;

ZMA (Zinc Magnesium Aspartate; Examine) is a supplement mix of zinc, magnesium and vitamin B6. The combination is semi-popular for athletes/weight-lifters but it’s also commonly said to be good for sleep, perhaps due to the magnesium. I haven’t looked at the research literature on it specifically, of which there is not much, but come on - how harmful could zinc, magnesium, or vitamin B6 be? Seemed worth a shot, and more than one person has asked me about it. So testing ZMA has for a long time been a (low) priority in my sleep experiments.

In March 2017, nootropics website Powder City announced a going-out-of-business sale (speculated to be due to a wrongful-death lawsuit over a guy who decided to commit suicide using tianeptine, which was eventually settled); I took advantage of it to pick up caffeine, theanine, sulbutiamine, creatine and, since some other things I wanted had sold out, picked up 200g of ZMA powder for a total of $19.27 (after coupon & shipping). The suggested dose is ~2.5g/day (3 1cc scoops), with the contents listed as follows: • Vitamin B6 as Pyridoxine Hydrochloride: 10.5mg • Magnesium as aspartate: 250mg • Zinc as mono-l-methionine and aspartate: 30mg So my $\frac{200g}{2.5g}=80$ doses or $\frac{19.27}{80} = \0.24$ per dose. Because of my bad experience with potassium, I didn’t jump straight into a blinded self-experiment but I briefly used ZMA as directed before bedtime 22-27 March 2017. I didn’t notice anything bad or good (if ZMA does cause weird dreams, it apparently did not do anything noticeable for me beyond what melatonin use causes) so I moved on. # Design ZMA doesn’t require anything special for a blinded self-experiment, as it’s a normal white powder without an overwhelming taste, so it can be simply capped. I took the remaining 185g/75 doses and capped 216 ZMA pills (24x9 batches); I capped a corresponding 240 flour pills. Total time capping & cleaning: 2h - ZMA powder, like magnesium citrate powder, is a pain to cap because it is a fluffy sticky powder which eventually starts to jam the pill machine, requiring it to be washed and thoroughly dried before doing a second batch. With 185g turning into 216 pills, that implies ~0.86g/pill, requiring 3 pills to reach the target dose of ~2.57g; at 3 pills per night, 72 nights of ZMA or 144 days total. For simplicity I went with my usual blinding & randomization method of paired-days / paired-jars. Because my sample size is limited by how much ZMA I had on hand, I did not do any power analysis. The experiment ran from 30 March 2017 to 9 October 2017. I ran into two major issues: there were a large number of interruptions due to forgetting or travel (eg a meditation retreat) or other issues, and my Zeo data quality appears to be declining considerably, with both missing-nights increasing & ZQ dropping improbably much (perhaps because my last headband is wearing out or due to subtle electrical-wiring issues again screwing with voltage) - that or my sleep really did degrade that drastically over 2016-2017. As well, my other magnesium experiments suggest there are cumulative effects of magnesium supplementation which blocking pairs of days would hide, but I haven’t confirmed this and discussions of ZMA/sleep claim acute benefits. Between these problems, I am unhappy with how the experiment’s quality turned out: the sample size was too low to start with, the Zeo data issues decreased it further with noisier & missing data, and the causal interpretation is a little shaky. zma <- read.csv("~/wiki/docs/zeo/2018-01-04-zeo-zma.csv", colClasses=c("Date", rep("integer", 11))) l <- lm(cbind(ZQ, Total.Z, Time.to.Z, Time.in.Wake, Time.in.REM, Time.in.Light, Time.in.Deep, Awakenings, Rise.Time, Morning.Feel) ~ ZMA, data=zma); summary(l) # Response ZQ : # Coefficients: # Estimate Std. Error t value Pr(>|t|) # (Intercept) 57.692308 2.882334 20.01583 < 2e-16 # ZMA 4.839950 4.125251 1.17325 0.24293 # # Residual standard error: 23.23812 on 125 degrees of freedom # (72 observations deleted due to missingness) # Multiple R-squared: 0.01089218, Adjusted R-squared: 0.002979316 # F-statistic: 1.376516 on 1 and 125 DF, p-value: 0.2429264 # # Response Total.Z : # Coefficients: # Estimate Std. Error t value Pr(>|t|) # (Intercept) 353.47692 16.12152 21.92578 < 2e-16 # ZMA 19.08759 23.07342 0.82725 0.40967 # # Residual standard error: 129.9759 on 125 degrees of freedom # (72 observations deleted due to missingness) # Multiple R-squared: 0.00544499, Adjusted R-squared: -0.00251145 # F-statistic: 0.68435 on 1 and 125 DF, p-value: 0.4096693 # # Response Time.to.Z : # Coefficients: # Estimate Std. Error t value Pr(>|t|) # (Intercept) 8.0000000 1.1118491 7.19522 5.0703e-11 # ZMA -0.6451613 1.5912993 -0.40543 0.68585 # # Residual standard error: 8.964014 on 125 degrees of freedom # (72 observations deleted due to missingness) # Multiple R-squared: 0.001313264, Adjusted R-squared: -0.00667623 # F-statistic: 0.1643739 on 1 and 125 DF, p-value: 0.6858542 # # Response Time.in.Wake : # Coefficients: # Estimate Std. Error t value Pr(>|t|) # (Intercept) 19.615385 2.683811 7.30878 2.8102e-11 # ZMA -3.470223 3.841120 -0.90344 0.36803 # # Residual standard error: 21.63757 on 125 degrees of freedom # (72 observations deleted due to missingness) # Multiple R-squared: 0.006487277, Adjusted R-squared: -0.001460825 # F-statistic: 0.8162046 on 1 and 125 DF, p-value: 0.36803 # # Response Time.in.REM : # Coefficients: # Estimate Std. Error t value Pr(>|t|) # (Intercept) 66.184615 5.562789 11.89774 < 2e-16 # ZMA 12.379901 7.961568 1.55496 0.12248 # # Residual standard error: 44.84864 on 125 degrees of freedom # (72 observations deleted due to missingness) # Multiple R-squared: 0.01897609, Adjusted R-squared: 0.0111279 # F-statistic: 2.417893 on 1 and 125 DF, p-value: 0.1224844 # # Response Time.in.Light : # Coefficients: # Estimate Std. Error t value Pr(>|t|) # (Intercept) 254.123077 10.926307 23.25791 < 2e-16 # ZMA 3.554342 15.637936 0.22729 0.82057 # # Residual standard error: 88.09071 on 125 degrees of freedom # (72 observations deleted due to missingness) # Multiple R-squared: 0.0004131143, Adjusted R-squared: -0.007583581 # F-statistic: 0.05166063 on 1 and 125 DF, p-value: 0.8205698 # # Response Time.in.Deep : # Coefficients: # Estimate Std. Error t value Pr(>|t|) # (Intercept) 33.707692 2.495414 13.50785 < 2e-16 # ZMA 3.098759 3.571484 0.86764 0.38725 # # Residual standard error: 20.11867 on 125 degrees of freedom # (72 observations deleted due to missingness) # Multiple R-squared: 0.005986331, Adjusted R-squared: -0.001965779 # F-statistic: 0.7527978 on 1 and 125 DF, p-value: 0.3872545 # # Response Awakenings : # Coefficients: # Estimate Std. Error t value Pr(>|t|) # (Intercept) 4.9384615 0.4312593 11.45126 < 2e-16 # ZMA -0.6965261 0.6172264 -1.12848 0.26128 # # Residual standard error: 3.476924 on 125 degrees of freedom # (72 observations deleted due to missingness) # Multiple R-squared: 0.01008495, Adjusted R-squared: 0.002165627 # F-statistic: 1.273461 on 1 and 125 DF, p-value: 0.2612796 # # Response Rise.Time : # Coefficients: # Estimate Std. Error t value Pr(>|t|) # (Intercept) 555.230769 7.176394 77.36905 < 2e-16 # ZMA 7.946650 10.270989 0.77370 0.44057 # # Residual standard error: 57.85794 on 125 degrees of freedom # (72 observations deleted due to missingness) # Multiple R-squared: 0.004766052, Adjusted R-squared: -0.003195819 # F-statistic: 0.5986096 on 1 and 125 DF, p-value: 0.4405698 # # Response Morning.Feel : # Coefficients: # Estimate Std. Error t value Pr(>|t|) # (Intercept) 2.16923077 0.11124903 19.49887 < 2e-16 # ZMA -0.07245658 0.15922170 -0.45507 0.64985 # # Residual standard error: 0.8969184 on 125 degrees of freedom # (72 observations deleted due to missingness) # Multiple R-squared: 0.001653949, Adjusted R-squared: -0.006332819 # F-statistic: 0.2070862 on 1 and 125 DF, p-value: 0.6498503 summary(manova(l)) # Df Pillai approx F num Df den Df Pr(>F) # ZMA 1 0.087584221 0.91191989 12 114 0.53755 # Residuals 125 # Table: Variable Effect p-value Better ZQ 4.84 0.24 Yes Total Z 19.1 0.41 Yes Time to Z -0.65 0.69 Yes Time in Wake -3.47 0.37 Yes Time in REM 12.38 0.12 Yes Time in Light 3.55 0.82 ? Time in Deep 3.09 0.39 Yes Awakenings -0.69 0.26 Yes zma$Total.Z.2 <- zma$Total.Z^2 zma$ZQ.2 <- zma$ZQ^2 zma$Time.in.REM.2 <- zma$Time.in.REM^2 zma$Time.in.Light.2 <- zma$Time.in.Light^2 zma$Time.in.Wake.log <- log1p(zma$Time.in.Wake) zma$Time.to.Z.log <- log1p(zma$Time.to.Z) # reduce skew zma$Awakenings <- zma$Awakenings library(blavaan) model1 <- ' # single-indicator measurement error model for each sleep variable assuming decent reliability: ZQ.2_latent =~ 1*ZQ.2 ZQ.2 ~~ 0.7*ZQ.2 Total.Z.2_latent =~ 1*Total.Z.2 Total.Z.2 ~~ 0.7*Total.Z.2 Time.in.REM.2_latent =~ 1*Time.in.REM.2 Time.in.REM.2 ~~ 0.7*Time.in.REM.2 Time.in.Light.2_latent =~ 1*Time.in.Light.2 Time.in.Light.2 ~~ 0.7*Time.in.Light.2 Time.in.Deep_latent =~ 1*Time.in.Deep Time.in.Deep ~~ 0.7*Time.in.Deep Time.to.Z.log_latent =~ 1*Time.to.Z.log Time.to.Z.log ~~ 0.7*Time.to.Z.log Time.in.Wake.log_latent =~ 1*Time.in.Wake.log Time.in.Wake.log ~~ 0.7*Time.in.Wake.log Awakenings_latent =~ 1*Awakenings Awakenings ~~ 0.7*Awakenings GOOD_SLEEP =~ ZQ.2_latent + Total.Z.2_latent + Time.in.REM.2_latent + Time.in.Light.2_latent + Time.in.Deep_latent + Morning.Feel BAD_SLEEP =~ Time.to.Z.log_latent + Time.in.Wake.log_latent + Awakenings_latent GOOD_SLEEP ~ ZMA BAD_SLEEP ~ ZMA ' # library(lavaan) # s1 <- sem(model1, missing="FIML", data=scale(night[-1])); summary(s1) system.time(s1 <- bsem(model1, test="none", n.chains=8, burnin=2000, sample=6000, dp = dpriors(nu = "dnorm(0,1)", alpha = "dnorm(0,1)", beta = "dnorm(0,200)"), jagcontrol=list(method="rjparallel"), fixed.x=FALSE, data=scale(zma[-1]))); summary(s1) ## munging the MCMC matrix/lists, appears to be variables 26,27 as of 2018-01-04, blavaan version 0.2-4: # beta[9,11,1] -0.064641 0.042357 0.14972 0.042289 0.0548 -- 0.00045562 0.8 14466 0.035169 1.0001 posteriorGood <- [email protected]$mcmcout$mcmc[1][,26][[1]] # beta[10,11,1] -0.11429 -0.033242 0.046418 -0.033257 0.040809 -- 0.00049508 1.2 6795 0.11383 1.0003 posteriorBad <- [email protected]$mcmcout\$mcmc[1][,27][[1]]
mean(posteriorGood>0)
# [1] 0.7778333333
mean(posteriorBad<0)
# [1] 0.7896666667