Hypotheses will be tested using Generalized Linear Mixed-Effect Models (Lo & Andrews, 2015) with Condition as a fixed effect and child (participant) as a random intercept, and with appropriate linking functions.
The model for Study Time will have an inverse Gaussian linking function because of its similar distribution to reaction times (Lo & Andrews, 2015).
The model for Memory Usage will have an identity linking function because based on the results of our previous studies, we expect it to follow a normal distribution. If there are substantive violations of the assumptions of these analyses, we will corroborate results with analogous non-parametric tests.
Load libraries and data
library(tidyverse)
Warning: package 'tidyverse' was built under R version 4.2.3
Warning: package 'ggplot2' was built under R version 4.2.3
Warning: package 'readr' was built under R version 4.2.3
Warning: package 'stringr' was built under R version 4.2.3
Warning: package 'forcats' was built under R version 4.2.3
Warning: package 'lubridate' was built under R version 4.2.3
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr 1.0.10 ✔ readr 2.1.4
✔ forcats 1.0.0 ✔ stringr 1.5.0
✔ ggplot2 3.5.1 ✔ tibble 3.1.8
✔ lubridate 1.9.2 ✔ tidyr 1.2.1
✔ purrr 0.3.4
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag() masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(ggpubr)library(ggforce)
Warning: package 'ggforce' was built under R version 4.2.3
library(effectsize)library(lme4)
Warning: package 'lme4' was built under R version 4.2.3
Loading required package: Matrix
Attaching package: 'Matrix'
The following objects are masked from 'package:tidyr':
expand, pack, unpack
library(lmerTest)
Warning: package 'lmerTest' was built under R version 4.2.3
Attaching package: 'lmerTest'
The following object is masked from 'package:lme4':
lmer
The following object is masked from 'package:stats':
step
library(emmeans)
Warning: package 'emmeans' was built under R version 4.2.3
library(MuMIn)
Warning: package 'MuMIn' was built under R version 4.2.3
library(MCMCglmm)
Warning: package 'MCMCglmm' was built under R version 4.2.3
Loading required package: coda
Warning: package 'coda' was built under R version 4.2.3
Loading required package: ape
Warning: package 'ape' was built under R version 4.2.3
Attaching package: 'ape'
The following object is masked from 'package:ggpubr':
rotate
library(mixedpower)library(DHARMa)
Warning: package 'DHARMa' was built under R version 4.2.3
This is DHARMa 0.4.6. For overview type '?DHARMa'. For recent changes, type news(package = 'DHARMa')
# Disable scientific notationoptions(scipen =999)# Set working directory if working locallysetwd("D:/Canna_d/EM5_stuff/EM5_April_2025")# Read in filedata <-read.csv("Summarized_first_trips_April25.csv", header =TRUE)# label closing trialdata$condsFile <-ifelse(data$trial ==4, paste0(data$condsFile, "Closing"), data$condsFile)# Read in file for age and combine with dataages <-read.csv("ages.csv", header = T)data <-left_join(data, ages, by ="participant")# Make output more interpretableoptions(contrasts =c("contr.sum","contr.poly"))
Study time
Process data
# Average over all trials for each condition, for each child, as per preregistrationsummarized_data <- data %>%group_by(participant, condsFile) %>%summarize(mean_MU =mean(meanMU, na.rm =TRUE),mean_StudyTime =mean(meanListTime, na.rm =TRUE),mean_Streak =mean(meanCorBefInc, na.rm =TRUE),age =first(Age),.groups ='drop')# make sure condition is a factorsummarized_data$condsFile <-as.factor(summarized_data$condsFile)# Remove closing trialsfreeResponseOnly <- summarized_data %>%filter(!(condsFile %in%c("noDelayClosing", "longDelayClosing")))
Model study time
# Run the modelstudyTimeGlmm <-glmer(mean_StudyTime ~ condsFile + (1|participant), data = freeResponseOnly, family =inverse.gaussian(link ="identity"))# no errors or warnings# Looks OK 4/12/25plot(density(freeResponseOnly$mean_StudyTime), xlim=c(0, 160), ylim=c(0, 1), main='M_1 y_hat')lines(density(predict(studyTimeGlmm, type='response')), col='red')
# Heteroskedasticity 4/12plot(studyTimeGlmm)
# Looks good to me 4/12residuals <-residuals(studyTimeGlmm)qqnorm(residuals)qqline(residuals, col ="red")
# Get an overall checklibrary(performance)check_model(studyTimeGlmm)
Loading required namespace: statmod
Simulations from your fitted model produce infinite values. Consider if this is sensible
Cannot simulate residuals for models of class `glmerMod`. Please try
`check_model(..., residual_type = "normal")` instead.
# Heterogeneity of variance.....# Below we will compare model with one that has no fixed effects# To see if the fixed effects (condsFile) is important at explaining the datamixConTime_GLMM_null <-glmer(mean_StudyTime ~1+ (1|participant), data = freeResponseOnly, family =inverse.gaussian(link ="identity"))
Warning in checkConv(attr(opt, "derivs"), opt$par, ctrl = control$checkConv, :
Model failed to converge with max|grad| = 0.0721721 (tol = 0.002, component 1)
Warning in checkConv(attr(opt, "derivs"), opt$par, ctrl = control$checkConv, : Model is nearly unidentifiable: very large eigenvalue
- Rescale variables?
# Null model failed to converge?mixTimeConAov <-cbind(car::Anova(studyTimeGlmm),r.squaredGLMM(studyTimeGlmm,mixConTime_GLMM_null))
Warning: 'r.squaredGLMM' now calculates a revised statistic. See the help page.
# Compare the modelsanova(mixConTime_GLMM_null,studyTimeGlmm)
To check the distribution of age and to (exploratory) see if age has an effect on any DV’s.
# Run the KS testks.test(freeResponseOnly$age, "punif", min(freeResponseOnly$age), max(freeResponseOnly$age))
Warning in ks.test.default(freeResponseOnly$age, "punif",
min(freeResponseOnly$age), : ties should not be present for the
Kolmogorov-Smirnov test
Asymptotic one-sample Kolmogorov-Smirnov test
data: freeResponseOnly$age
D = 0.20422, p-value = 0.000008008
alternative hypothesis: two-sided
# Plot the density of actual dataplot(density(freeResponseOnly$age), main ="Age Distribution vs Uniform", xlab ="Age", ylab ="Density", xlim =c(min(freeResponseOnly$age), max(freeResponseOnly$age)),lwd =2)# Add a horizontal line for the uniform distribution's densityabline(h =1/ (max(freeResponseOnly$age) -min(freeResponseOnly$age)), col ="red", lty =2, lwd =2)legend("topright", legend =c("Observed Density", "Uniform Density"),col =c("black", "red"), lty =c(1,2), lwd =2)
# Center agefreeResponseOnly$age.ct <- freeResponseOnly$age -mean(freeResponseOnly$age)# Run the age model for study timestudyTimeGlmmAge <-glmer(mean_StudyTime ~ condsFile ++ age.ct + age.ct*condsFile + (1|participant), data = freeResponseOnly, family =inverse.gaussian(link ="identity"))# no errors or warnings# Looks OK 4/21/25plot(density(freeResponseOnly$mean_StudyTime), xlim=c(0, 160), ylim=c(0, 1), main='M_1 y_hat')lines(density(predict(studyTimeGlmmAge, type='response')), col='red')
# Heteroskedasticity 4/21plot(studyTimeGlmmAge)
# Looks good to me 4/21residuals <-residuals(studyTimeGlmmAge)qqnorm(residuals)qqline(residuals, col ="red")
# Looks good 4/21library(performance)check_model(studyTimeGlmmAge)
Simulations from your fitted model produce infinite values. Consider if this is sensible
Cannot simulate residuals for models of class `glmerMod`. Please try
`check_model(..., residual_type = "normal")` instead.
# Below we will compare model with one that has no fixed effects# To see if the fixed effects (condsFile) is important at explaining the datamixConTime_GLMM_null <-glmer(mean_StudyTime ~1+ (1|participant), data = freeResponseOnly, family =inverse.gaussian(link ="identity"))
Warning in checkConv(attr(opt, "derivs"), opt$par, ctrl = control$checkConv, :
Model failed to converge with max|grad| = 0.0721721 (tol = 0.002, component 1)
Warning in checkConv(attr(opt, "derivs"), opt$par, ctrl = control$checkConv, : Model is nearly unidentifiable: very large eigenvalue
- Rescale variables?
# Null model failed to converge?mixTimeConAov <-cbind(car::Anova(studyTimeGlmmAge),r.squaredGLMM(studyTimeGlmmAge,mixConTime_GLMM_null)) # Compare the modelsanova(mixConTime_GLMM_null,studyTimeGlmmAge)
# The full model fits better 4/21/25summary(studyTimeGlmmAge)
Generalized linear mixed model fit by maximum likelihood (Laplace
Approximation) [glmerMod]
Family: inverse.gaussian ( identity )
Formula: mean_StudyTime ~ condsFile + +age.ct + age.ct * condsFile + (1 |
participant)
Data: freeResponseOnly
AIC BIC logLik deviance df.resid
619.4 637.4 -303.7 607.4 143
Scaled residuals:
Min 1Q Median 3Q Max
-1.80065 -0.52542 -0.09949 0.38394 2.36748
Random effects:
Groups Name Variance Std.Dev.
participant (Intercept) 3.04963 1.7463
Residual 0.02351 0.1533
Number of obs: 149, groups: participant, 75
Fixed effects:
Estimate Std. Error t value Pr(>|z|)
(Intercept) 6.2127 0.3753 16.555 < 0.0000000000000002 ***
condsFile1 0.2716 0.1050 2.587 0.00969 **
age.ct -0.3665 0.7453 -0.492 0.62289
condsFile1:age.ct 0.4024 0.2364 1.702 0.08867 .
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Correlation of Fixed Effects:
(Intr) cndsF1 age.ct
condsFile1 -0.019
age.ct 0.102 0.040
cndsFl1:g.c 0.033 -0.198 0.061
# No delay has less study time than long delay, sig 4/21# Age fixed effect non sig# Older kids marginally study in no delay for less time
Plot study time
Age effects plot
# Define the levels of condsFileconds_levels <-c("noDelay", "longDelay")# Define colors for each conditioncolors <-c("#0072B2", "#D55E00")# Create an empty plotplot(NA, xlim =range(freeResponseOnly$age), ylim =c(0, 20), # Adjusted y-axis rangexlab ="Age", ylab ="Study time (seconds)",main ="",cex.lab =1.6, # Axis labels (xlab, ylab)cex.axis =1.5, # Tick labelscex.main =1.2# Title)# Add points and trend lines for each conditionfor (i in1:length(conds_levels)) {# Filter data for the current condition condition_data <- freeResponseOnly[freeResponseOnly$condsFile == conds_levels[i], ]# Add pointspoints(condition_data$age, condition_data$mean_StudyTime, col =adjustcolor(colors[i], alpha.f =0.4), pch =16)# Add a trend line (linear regression line)abline(lm(mean_StudyTime ~ age, data = condition_data), col = colors[i], lwd =2)}# Add a legend to the plotlegend("topright", legend = conds_levels, col = colors, lty =1, lwd =2, pch =16)
Memory Usage
Model for MU
# View the distribution of MUhist(freeResponseOnly$mean_MU)
# Run the modelMU_GLMM <-glmer(mean_MU ~ condsFile + (1|participant),data = freeResponseOnly, family =gaussian(link ="identity"))
Warning in glmer(mean_MU ~ condsFile + (1 | participant), data =
freeResponseOnly, : calling glmer() with family=gaussian (identity link) as a
shortcut to lmer() is deprecated; please call lmer() directly
# No errors etc. It says this is an lmer, truee# Could be better 4/12plot(density(freeResponseOnly$mean_MU), xlim=c(-50, 50), ylim=c(0, 0.6), main='M_1 y_hat')lines(density(predict(MU_GLMM, type='response') ), col='red')
# Heteroskedasticity 4/12plot(MU_GLMM)
# The qq plot is quite wiggly in the upper tail 4/12residuals <-residuals(MU_GLMM)qqnorm(residuals)qqline(residuals, col ="red")
# This model does not fit very well... 4/12check_model(MU_GLMM)
MUfree_null <-glmer(mean_MU ~1+ (1|participant), data = freeResponseOnly, family =gaussian(link ="identity"))
Warning in glmer(mean_MU ~ 1 + (1 | participant), data = freeResponseOnly, :
calling glmer() with family=gaussian (identity link) as a shortcut to lmer() is
deprecated; please call lmer() directly
MUfreeAov <-cbind(car::Anova(MU_GLMM),r.squaredGLMM(MU_GLMM,MUfree_null))# The null not necessarily fitting better but less AIC 4/12anova(MUfree_null,MU_GLMM)
# No delay has less MU but it is non-significant!summary(MU_GLMM)
Linear mixed model fit by REML ['lmerMod']
Formula: mean_MU ~ condsFile + (1 | participant)
Data: freeResponseOnly
REML criterion at convergence: 438.7
Scaled residuals:
Min 1Q Median 3Q Max
-1.9526 -0.5412 -0.1849 0.4072 4.3791
Random effects:
Groups Name Variance Std.Dev.
participant (Intercept) 0.3115 0.5581
Residual 0.8135 0.9020
Number of obs: 149, groups: participant, 75
Fixed effects:
Estimate Std. Error t value
(Intercept) 1.72009 0.09810 17.534
condsFile1 0.12453 0.07396 1.684
Correlation of Fixed Effects:
(Intr)
condsFile1 0.006
This is just an exploratory analysis. Don’t think we will do anything with this, was just comparing the results with MU.
# Try streak#library(glmmTMB)# Only on whole values!#streak_NB <- glmmTMB(mean_Streak ~ condsFile + (1|participant),# data = freeResponseOnly,# family = nbinom2) # or nbinom1 depending on the data# make sure condition is a factordata$condsFile <-as.factor(data$condsFile)# Remove closing trialsFR_rawdata <- data %>%filter(!(condsFile %in%c("noDelayClosing", "longDelayClosing")))# Run the modelstreakModel <-glmer.nb(meanCorBefInc ~ condsFile + (1|participant),data = FR_rawdata)
# not the best 4/21plot(density(FR_rawdata$meanCorBefInc), xlim=c(-50, 50), ylim=c(0, 0.6), main='M_1 y_hat')lines(density(predict(streakModel, type='response') ), col='red')
# ?? 4/21plot(streakModel)
# The qq plot is quite wiggly in the tail 4/21residuals <-residuals(streakModel)qqnorm(residuals)qqline(residuals, col ="red")
# Pfft what 4/21check_model(streakModel)
streak_null <-glmer.nb(meanCorBefInc ~1+ (1|participant), data = FR_rawdata)
# Also there were weird warnings# Replicate Bill's model:streak_lmer <-lmer(mean_Streak ~ condsFile + (1|participant),data = freeResponseOnly)plot(streak_lmer) # heteroskedatsic 4/21
summary(streak_lmer)
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula: mean_Streak ~ condsFile + (1 | participant)
Data: freeResponseOnly
REML criterion at convergence: 440.8
Scaled residuals:
Min 1Q Median 3Q Max
-1.6181 -0.5669 -0.1768 0.3657 4.6999
Random effects:
Groups Name Variance Std.Dev.
participant (Intercept) 0.4233 0.6506
Residual 0.7524 0.8674
Number of obs: 149, groups: participant, 75
Fixed effects:
Estimate Std. Error df t value Pr(>|t|)
(Intercept) 1.92508 0.10347 74.09021 18.605 <0.0000000000000002 ***
condsFile1 0.12508 0.07115 73.72598 1.758 0.0829 .
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Correlation of Fixed Effects:
(Intr)
condsFile1 0.006
# No delay has less of a streak, but non-sig 4/21
Age effects model
# Run the model for age effects with MUMU_GLMMAge <-glmer(mean_MU ~ condsFile ++ age.ct + age.ct*condsFile + (1|participant),data = freeResponseOnly, family =gaussian(link ="identity"))
Warning in glmer(mean_MU ~ condsFile + +age.ct + age.ct * condsFile + (1 | :
calling glmer() with family=gaussian (identity link) as a shortcut to lmer() is
deprecated; please call lmer() directly
# No errors etc. It says this is an lmer, truee # Could be better 4/21plot(density(freeResponseOnly$mean_MU), xlim=c(-50, 50), ylim=c(0, 0.6), main='M_1 y_hat')lines(density(predict(MU_GLMMAge, type='response') ), col='red')
# Heteroskedasticity 4/21plot(MU_GLMMAge)
# The qq plot is quite wiggly in the upper tail 4/21residuals <-residuals(MU_GLMMAge)qqnorm(residuals)qqline(residuals, col ="red")
# This model does not fit very well... 4/21check_model(MU_GLMMAge)
MUfree_null <-glmer(mean_MU ~1+ (1|participant), data = freeResponseOnly, family =gaussian(link ="identity"))
Warning in glmer(mean_MU ~ 1 + (1 | participant), data = freeResponseOnly, :
calling glmer() with family=gaussian (identity link) as a shortcut to lmer() is
deprecated; please call lmer() directly
MUfreeAov <-cbind(car::Anova(MU_GLMMAge),r.squaredGLMM(MU_GLMMAge,MUfree_null))# The null not necessarily fitting better and less AIC 4/21anova(MUfree_null,MU_GLMMAge)
# Define the levels of condsFileconds_levels <-c("noDelay", "longDelay")# Define colors for each conditioncolors <-c("#0072B2", "#D55E00")# Create an empty plotplot(NA, xlim =range(freeResponseOnly$age), ylim =c(-5, 10), # Adjusted y-axis rangexlab ="Age", ylab ="Memory Usage (items)",main ="",cex.lab =1.6, # Axis labels (xlab, ylab)cex.axis =1.5, # Tick labelscex.main =1.2# Title)# Add points and trend lines for each conditionfor (i in1:length(conds_levels)) {# Filter data for the current condition condition_data <- freeResponseOnly[freeResponseOnly$condsFile == conds_levels[i], ]# Add pointspoints(condition_data$age, condition_data$mean_MU, col =adjustcolor(colors[i], alpha.f =0.4), pch =16)# Add a trend line (linear regression line)abline(lm(mean_MU ~ age, data = condition_data), col = colors[i], lwd =2)}# Add a legend to the plotlegend("topright", legend = conds_levels, col = colors, lty =1, lwd =2, pch =16)
Free VS Total response
Process Free V Total
library(dplyr)# Label cond-type to say if its free or total-responsesummarized_data <- summarized_data %>%mutate(condType =case_when( condsFile %in%c("noDelayClosing", "longDelayClosing") ~"Total", condsFile %in%c("noDelay", "longDelay") ~"Free",TRUE~NA_character_ ))# Average over participant and conditionfreeVtotal <- summarized_data %>%group_by(participant, condType) %>%summarize(mean_MU =mean(mean_MU, na.rm =TRUE),mean_StudyTime =mean(mean_StudyTime, na.rm =TRUE),age =first(age),.groups ='drop')
Model free V total
# Observe distributionhist(freeVtotal$mean_MU)
# Run the modelfreeVtotal_glmm <-glmer(mean_MU ~ condType + (1|participant),data = freeVtotal, family =gaussian(link ="identity"))
Warning in glmer(mean_MU ~ condType + (1 | participant), data = freeVtotal, :
calling glmer() with family=gaussian (identity link) as a shortcut to lmer() is
deprecated; please call lmer() directly
# No errors etc. It says this is an lmer, truee# Could be better 4/12plot(density(freeVtotal$mean_MU), xlim=c(-50, 50), ylim=c(0, 0.6), main='M_1 y_hat')lines(density(predict(freeVtotal_glmm, type='response') ), col='red')
# The qq plot is quite wiggly in both tails 4/12residuals <-residuals(freeVtotal_glmm)qqnorm(residuals)qqline(residuals, col ="red")
# This model does not fit very well... 4/12check_model(freeVtotal_glmm)
MUfree_null <-glmer(mean_MU ~1+ (1|participant), data = freeVtotal, family =gaussian(link ="identity"))
Warning in glmer(mean_MU ~ 1 + (1 | participant), data = freeVtotal, family =
gaussian(link = "identity")): calling glmer() with family=gaussian (identity
link) as a shortcut to lmer() is deprecated; please call lmer() directly
MUfreeAov <-cbind(car::Anova(freeVtotal_glmm),r.squaredGLMM(freeVtotal_glmm,MUfree_null))# The null not fitting better but less AIC 4/12anova(MUfree_null,freeVtotal_glmm)
# Free response has less MU but it is non-significant!summary(freeVtotal_glmm)
Linear mixed model fit by REML ['lmerMod']
Formula: mean_MU ~ condType + (1 | participant)
Data: freeVtotal
REML criterion at convergence: 635.5
Scaled residuals:
Min 1Q Median 3Q Max
-3.12767 -0.40792 0.03309 0.43621 2.86641
Random effects:
Groups Name Variance Std.Dev.
participant (Intercept) 0.9624 0.981
Residual 3.1610 1.778
Number of obs: 150, groups: participant, 75
Fixed effects:
Estimate Std. Error t value
(Intercept) 1.8511 0.1841 10.053
condType1 -0.1356 0.1452 -0.934
Correlation of Fixed Effects:
(Intr)
condType1 0.000
# Center agefreeVtotal$age.ct <- freeVtotal$age -mean(freeVtotal$age)# Run the modelfreeVtotal_glmmAge <-glmer(mean_MU ~ condType ++ age.ct + age.ct*condType+ (1|participant), data = freeVtotal, family =gaussian(link ="identity"))
Warning in glmer(mean_MU ~ condType + +age.ct + age.ct * condType + (1 | :
calling glmer() with family=gaussian (identity link) as a shortcut to lmer() is
deprecated; please call lmer() directly
# No errors etc. It says this is an lmer, truee# Could be better 4/21plot(density(freeVtotal$mean_MU), xlim=c(-50, 50), ylim=c(0, 0.6), main='M_1 y_hat')lines(density(predict(freeVtotal_glmmAge, type='response') ), col='red')
# Heteroskedasticity 4/21plot(freeVtotal_glmmAge)
# The qq plot is quite wiggly in both tails 4/21residuals <-residuals(freeVtotal_glmmAge)qqnorm(residuals)qqline(residuals, col ="red")
# This model does not fit very well... 4/21check_model(freeVtotal_glmmAge)
MUfree_null <-glmer(mean_MU ~1+ (1|participant), data = freeVtotal, family =gaussian(link ="identity"))
Warning in glmer(mean_MU ~ 1 + (1 | participant), data = freeVtotal, family =
gaussian(link = "identity")): calling glmer() with family=gaussian (identity
link) as a shortcut to lmer() is deprecated; please call lmer() directly
MUfreeAov <-cbind(car::Anova(freeVtotal_glmmAge),r.squaredGLMM(freeVtotal_glmmAge,MUfree_null))# The null not fitting better and less AIC 4/21anova(MUfree_null,freeVtotal_glmmAge)
# memory usage -----------# Calculate means and standard errorsmeans <-tapply(freeVtotal$mean_MU, freeVtotal$condType, mean)# Calculate standard deviations and sample sizes for each conditionsds <-tapply(freeVtotal$mean_MU, freeVtotal$condType, sd)n_per_condition <-tapply(freeVtotal$mean_MU, freeVtotal$condType, length)# Calculate standard errorsse <- sds /sqrt(n_per_condition)# Define the x-axis levels (to match the ggplot2 ordering)conds_levels <-c("Free", "Total")x_positions <-1:length(conds_levels)# Create an empty plotplot( x_positions, means[conds_levels], type ="n", xaxt ="n", ylim =c(-5, 10.0), xlim =c(0.5, 2.5),xlab ="", ylab ="Mean Memory Usage (items)", main ="",cex.lab =1.5,cex.axis =1.5,cex.main =1.5)participants <-unique(freeVtotal$participant)for (p in participants) { this_participant <- freeVtotal[freeVtotal$participant == p, ]if (nrow(this_participant) ==2) {# Get the x positions for this participant’s conditions x_vals <-match(this_participant$condType, conds_levels) y_vals <- this_participant$mean_MUlines(x_vals, y_vals, col =adjustcolor("#009E73", alpha.f =0.3), lwd =1) }}# Add x-axis labels normallyaxis(1, at = x_positions, labels = conds_levels, cex.axis =1.5)# Add points for each participantfor (i in1:length(conds_levels)) { condition_data <- freeVtotal[freeVtotal$condType == conds_levels[i], ]points(rep(x_positions[i], nrow(condition_data)), condition_data$mean_MU, pch =1, col ="#0072B2")}# Add points for the meanspoints(x_positions, means[conds_levels], pch =10, col ="black")# Add a solid line connecting the meanslines(x_positions, means[conds_levels], col ="black", lwd =2)# Add horizontal segments at the means (optional, similar to ggplot2's stat_summary)segments( x_positions -0.1, means[conds_levels], x_positions +0.1, means[conds_levels],col ="black", lwd =3.0)# Add mean labels for each conditiontext(x_positions, means[conds_levels] +2, labels =round(means[conds_levels], 2), cex =2.5, col ="black")# Add error bars using arrows() with specified lower and upper bounds# Function to compute standard errorse <-function(x) sd(x, na.rm =TRUE) /sqrt(sum(!is.na(x)))# Get standard errors for each conditionses <-tapply(freeVtotal$mean_MU, freeVtotal$condType, se)# Get means again, just to be suremeans <-tapply(freeVtotal$mean_MU, freeVtotal$condType, mean)# Define bounds for error barslower_bounds <- means[conds_levels] -2*ses[conds_levels]upper_bounds <- means[conds_levels] +2*ses[conds_levels]# Add vertical error bars using arrows()for (i in1:length(x_positions)) {arrows(x0 = x_positions[i], y0 = lower_bounds[i], x1 = x_positions[i], y1 = upper_bounds[i], length =0.1, angle =90, code =3, col ="#D55E00", lwd =3.5 )}
Free V Total age plot
# Define the levels of condsFileconds_levels <-c("Free", "Total")# Define colors for each conditioncolors <-c("#0072B2", "#D55E00")# Create an empty plotplot(NA, xlim =range(freeVtotal$age), ylim =c(-5, 10), # Adjusted y-axis rangexlab ="Age", ylab ="Memory Usage (items)",main ="",cex.lab =1.6, # Axis labels (xlab, ylab)cex.axis =1.5, # Tick labelscex.main =1.2# Title)# Add points and trend lines for each conditionfor (i in1:length(conds_levels)) {# Filter data for the current condition condition_data <- freeVtotal[freeVtotal$condType == conds_levels[i], ]# Add pointspoints(condition_data$age, condition_data$mean_MU, col =adjustcolor(colors[i], alpha.f =0.4), pch =16)# Add a trend line (linear regression line)abline(lm(mean_MU ~ age, data = condition_data), col = colors[i], lwd =2)}# Add a legend to the plotlegend("topright", legend = conds_levels, col = colors, lty =1, lwd =2, pch =16)
SRCD poster plots
par(mfrow =c(1, 2))# Rename values in the 'condsFile' columnfreeResponseOnly$condsFile <-as.character(freeResponseOnly$condsFile)freeResponseOnly$condsFile[freeResponseOnly$condsFile =="noDelay"] <-"No-Delay"freeResponseOnly$condsFile[freeResponseOnly$condsFile =="longDelay"] <-"Long-Delay"# study time ------------# Calculate meansmeans <-tapply(freeResponseOnly$mean_StudyTime, freeResponseOnly$condsFile, mean)# Define the x-axis levels (to match the ggplot2 ordering)conds_levels <-c("No-Delay", "Long-Delay")x_positions <-1:length(conds_levels)# Create an empty plotplot( x_positions, means[conds_levels], type ="n", xaxt ="n", ylim =c(0, 20.0), xlim =c(0.5, 2.5),xlab ="", ylab ="Mean Study Time (seconds)", main ="",cex.lab =1.5,cex.axis =1.5,cex.main =1.5)participants <-unique(freeResponseOnly$participant)for (p in participants) { this_participant <- freeResponseOnly[freeResponseOnly$participant == p, ]if (nrow(this_participant) ==2) {# Get the x positions for this participant’s conditions x_vals <-match(this_participant$condsFile, conds_levels) y_vals <- this_participant$mean_StudyTimelines(x_vals, y_vals, col =adjustcolor("#009E73", alpha.f =0.3), lwd =1) }}# Add x-axis labels normallyaxis(1, at = x_positions, labels = conds_levels, cex.axis =1.5)# Add points for each participantfor (i in1:length(conds_levels)) { condition_data <- freeResponseOnly[freeResponseOnly$condsFile == conds_levels[i], ]points(rep(x_positions[i], nrow(condition_data)), condition_data$mean_StudyTime, pch =1, col ="#0072B2")}# Add points for the meanspoints(x_positions, means[conds_levels], pch =10, col ="black")# Add a solid line connecting the meanslines(x_positions, means[conds_levels], col ="black", lwd =2)# Add horizontal segments at the means (optional, similar to ggplot2's stat_summary)segments( x_positions -0.1, means[conds_levels], x_positions +0.1, means[conds_levels],col ="black", lwd =3.0)# Add mean labels for each conditiontext(x_positions, means[conds_levels] +3, labels =round(means[conds_levels], 2), cex =2.5, col ="black")# Add error bars using arrows() with specified lower and upper bounds# Function to compute standard errorse <-function(x) sd(x, na.rm =TRUE) /sqrt(sum(!is.na(x)))# Get standard errors for each conditionses <-tapply(freeResponseOnly$mean_StudyTime, freeResponseOnly$condsFile, se)# Get means again, just to be suremeans <-tapply(freeResponseOnly$mean_StudyTime, freeResponseOnly$condsFile, mean)# Define bounds for error barslower_bounds <- means[conds_levels] -2*ses[conds_levels]upper_bounds <- means[conds_levels] +2*ses[conds_levels]# Add vertical error bars using arrows()for (i in1:length(x_positions)) {arrows(x0 = x_positions[i], y0 = lower_bounds[i], x1 = x_positions[i], y1 = upper_bounds[i], length =0.1, angle =90, code =3, col ="#D55E00", lwd =3.5 )}# memory usage -----------# Calculate means and standard errorsmeans <-tapply(freeResponseOnly$mean_MU, freeResponseOnly$condsFile, mean)# Calculate standard deviations and sample sizes for each conditionsds <-tapply(freeResponseOnly$mean_MU, freeResponseOnly$condsFile, sd)n_per_condition <-tapply(freeResponseOnly$mean_MU, freeResponseOnly$condsFile, length)# Calculate standard errorsse <- sds /sqrt(n_per_condition)# Define the x-axis levels (to match the ggplot2 ordering)conds_levels <-c("No-Delay", "Long-Delay")x_positions <-1:length(conds_levels)# Create an empty plotplot( x_positions, means[conds_levels], type ="n", xaxt ="n", ylim =c(-1, 7.0), xlim =c(0.5, 2.5),xlab ="", ylab ="Mean Memory Usage (items)", main ="",cex.lab =1.5,cex.axis =1.5,cex.main =1.5)participants <-unique(freeResponseOnly$participant)for (p in participants) { this_participant <- freeResponseOnly[freeResponseOnly$participant == p, ]if (nrow(this_participant) ==2) {# Get the x positions for this participant’s conditions x_vals <-match(this_participant$condsFile, conds_levels) y_vals <- this_participant$mean_MUlines(x_vals, y_vals, col =adjustcolor("#009E73", alpha.f =0.3), lwd =1) }}# Add x-axis labels normallyaxis(1, at = x_positions, labels = conds_levels, cex.axis =1.5)# Add points for each participantfor (i in1:length(conds_levels)) { condition_data <- freeResponseOnly[freeResponseOnly$condsFile == conds_levels[i], ]points(rep(x_positions[i], nrow(condition_data)), condition_data$mean_MU, pch =1, col ="#0072B2")}# Add points for the meanspoints(x_positions, means[conds_levels], pch =10, col ="black")# Add a solid line connecting the meanslines(x_positions, means[conds_levels], col ="black", lwd =2)# Add horizontal segments at the means (optional, similar to ggplot2's stat_summary)segments( x_positions -0.1, means[conds_levels], x_positions +0.1, means[conds_levels],col ="black", lwd =3.0)# Add mean labels for each conditiontext(x_positions, means[conds_levels] +2, labels =round(means[conds_levels], 2), cex =2.5, col ="black")# Add error bars using arrows() with specified lower and upper bounds# Function to compute standard errorse <-function(x) sd(x, na.rm =TRUE) /sqrt(sum(!is.na(x)))# Get standard errors for each conditionses <-tapply(freeResponseOnly$mean_MU, freeResponseOnly$condsFile, se)# Get means again, just to be suremeans <-tapply(freeResponseOnly$mean_MU, freeResponseOnly$condsFile, mean)# Define bounds for error barslower_bounds <- means[conds_levels] -2*ses[conds_levels]upper_bounds <- means[conds_levels] +2*ses[conds_levels]# Add vertical error bars using arrows()for (i in1:length(x_positions)) {arrows(x0 = x_positions[i], y0 = lower_bounds[i], x1 = x_positions[i], y1 = upper_bounds[i], length =0.1, angle =90, code =3, col ="#D55E00", lwd =3.5 )}
# Calculate means and standard errorsmeans <-tapply(freeVtotal$mean_MU, freeVtotal$condType, mean)# Calculate standard deviations and sample sizes for each conditionsds <-tapply(freeVtotal$mean_MU, freeVtotal$condType, sd)n_per_condition <-tapply(freeVtotal$mean_MU, freeVtotal$condType, length)# Calculate standard errorsse <- sds /sqrt(n_per_condition)# Define the x-axis levels (to match the ggplot2 ordering)conds_levels <-c("Free", "Total")x_positions <-1:length(conds_levels)# Create an empty plotplot( x_positions, means[conds_levels], type ="n", xaxt ="n", ylim =c(-5, 10.0), xlim =c(0.5, 2.5),xlab ="", ylab ="Mean Memory Usage (items)", main ="",cex.lab =1.5,cex.axis =1.5,cex.main =1.5)participants <-unique(freeVtotal$participant)for (p in participants) { this_participant <- freeVtotal[freeVtotal$participant == p, ]if (nrow(this_participant) ==2) {# Get the x positions for this participant’s conditions x_vals <-match(this_participant$condType, conds_levels) y_vals <- this_participant$mean_MUlines(x_vals, y_vals, col =adjustcolor("#009E73", alpha.f =0.3), lwd =1) }}# Add x-axis labels normallyaxis(1, at = x_positions, labels = conds_levels, cex.axis =1.6)# Add points for each participantfor (i in1:length(conds_levels)) { condition_data <- freeVtotal[freeVtotal$condType == conds_levels[i], ]points(rep(x_positions[i], nrow(condition_data)), condition_data$mean_MU, pch =1, col ="#0072B2")}# Add points for the meanspoints(x_positions, means[conds_levels], pch =10, col ="black")# Add a solid line connecting the meanslines(x_positions, means[conds_levels], col ="black", lwd =2)# Add horizontal segments at the means (optional, similar to ggplot2's stat_summary)segments( x_positions -0.1, means[conds_levels], x_positions +0.1, means[conds_levels],col ="black", lwd =3.0)# Add mean labels for each conditiontext(x_positions, means[conds_levels] +2, labels =round(means[conds_levels], 2), cex =2.5, col ="black")# Add error bars using arrows() with specified lower and upper bounds# Function to compute standard errorse <-function(x) sd(x, na.rm =TRUE) /sqrt(sum(!is.na(x)))# Get standard errors for each conditionses <-tapply(freeVtotal$mean_MU, freeVtotal$condType, se)# Get means again, just to be suremeans <-tapply(freeVtotal$mean_MU, freeVtotal$condType, mean)# Define bounds for error barslower_bounds <- means[conds_levels] -2*ses[conds_levels]upper_bounds <- means[conds_levels] +2*ses[conds_levels]# Add vertical error bars using arrows()for (i in1:length(x_positions)) {arrows(x0 = x_positions[i], y0 = lower_bounds[i], x1 = x_positions[i], y1 = upper_bounds[i], length =0.1, angle =90, code =3, col ="#D55E00", lwd =3.5 )}
EM5 1 plots
par(mfrow =c(1, 2))study_time <-read.csv("study_time.csv", header =TRUE)MU_data <-read.csv("MU_data.csv", header =TRUE)# Rename values in the 'condsFile' columnstudy_time$condsFile[study_time$condsFile =="noDelay"] <-"No-Delay"study_time$condsFile[study_time$condsFile =="longDelay"] <-"Long-Delay"study_time$condsFile[study_time$condsFile =="totalResponse"] <-"One-shot"# study time ------------# Calculate meansmeans <-tapply(study_time$mean_StudyTime, study_time$condsFile, mean)# Define the x-axis levels (to match the ggplot2 ordering)conds_levels <-c("No-Delay", "Long-Delay", "One-shot")x_positions <-1:length(conds_levels)# Create an empty plotplot( x_positions, means[conds_levels], type ="n", xaxt ="n", ylim =c(0, 30.0), xlim =c(0.5, 3.5),xlab ="", ylab ="Mean Study Time (seconds)", main ="",cex.lab =1.5,cex.axis =1.5,cex.main =1.1)participants <-unique(study_time$participant)for (p in participants) { this_participant <- study_time[study_time$participant == p, ]if (nrow(this_participant) ==3) {# Get the x positions for this participant’s conditions x_vals <-match(this_participant$condsFile, conds_levels) y_vals <- this_participant$mean_StudyTimelines(x_vals, y_vals, col =adjustcolor("#009E73", alpha.f =0.3), lwd =1) }}# Add x-axis labels normallyaxis(1, at = x_positions, labels = conds_levels, cex.axis =1.2)# Add points for each participantfor (i in1:length(conds_levels)) { condition_data <- study_time[study_time$condsFile == conds_levels[i], ]points(rep(x_positions[i], nrow(condition_data)), condition_data$mean_StudyTime, pch =1, col ="#0072B2")}# Add points for the meanspoints(x_positions, means[conds_levels], pch =10, col ="black")# Add a solid line connecting the meanslines(x_positions, means[conds_levels], col ="black", lwd =2)# Add horizontal segments at the means (optional, similar to ggplot2's stat_summary)segments( x_positions -0.1, means[conds_levels], x_positions +0.1, means[conds_levels],col ="black", lwd =3.0)# Add mean labels for each conditiontext(x_positions, means[conds_levels] +3, labels =round(means[conds_levels], 2), cex =2.5, col ="black")# Add error bars using arrows() with specified lower and upper bounds# Function to compute standard errorse <-function(x) sd(x, na.rm =TRUE) /sqrt(sum(!is.na(x)))# Get standard errors for each conditionses <-tapply(study_time$mean_StudyTime, study_time$condsFile, se)# Get means again, just to be suremeans <-tapply(study_time$mean_StudyTime, study_time$condsFile, mean)# Define bounds for error barslower_bounds <- means[conds_levels] -2*ses[conds_levels]upper_bounds <- means[conds_levels] +2*ses[conds_levels]# Add vertical error bars using arrows()for (i in1:length(x_positions)) {arrows(x0 = x_positions[i], y0 = lower_bounds[i], x1 = x_positions[i], y1 = upper_bounds[i], length =0.1, angle =90, code =3, col ="#D55E00", lwd =3.5 )}# MU ------------MU_data$condsFile[MU_data$condsFile =="noDelay"] <-"No-Delay"MU_data$condsFile[MU_data$condsFile =="longDelay"] <-"Long-Delay"MU_data$condsFile[MU_data$condsFile =="totalResponse"] <-"One-shot"# Calculate means and standard errorsmeans <-tapply(MU_data$mean_MU, MU_data$condsFile, mean)# Calculate standard deviations and sample sizes for each conditionsds <-tapply(MU_data$mean_MU, MU_data$condsFile, sd)n_per_condition <-tapply(MU_data$mean_MU, MU_data$condsFile, length)# Calculate standard errorsse <- sds /sqrt(n_per_condition)# Define the x-axis levels (to match the ggplot2 ordering)conds_levels <-c("No-Delay", "Long-Delay", "One-shot")x_positions <-1:length(conds_levels)# Create an empty plotplot( x_positions, means[conds_levels], type ="n", xaxt ="n", ylim =c(-5, 10.0), xlim =c(0.5, 3.5),xlab ="", ylab ="Mean Memory Usage (items)", main ="",cex.lab =1.5,cex.axis =1.5,cex.main =1.1)participants <-unique(MU_data$participant)for (p in participants) { this_participant <- MU_data[MU_data$participant == p, ]if (nrow(this_participant) ==3) {# Get the x positions for this participant’s conditions x_vals <-match(this_participant$condsFile, conds_levels) y_vals <- this_participant$mean_MUlines(x_vals, y_vals, col =adjustcolor("#009E73", alpha.f =0.3), lwd =1) }}# Add x-axis labels normallyaxis(1, at = x_positions, labels = conds_levels, cex.axis =1.2)# Add points for each participantfor (i in1:length(conds_levels)) { condition_data <- MU_data[MU_data$condsFile == conds_levels[i], ]points(rep(x_positions[i], nrow(condition_data)), condition_data$mean_MU, pch =1, col ="#0072B2")}# Add points for the meanspoints(x_positions, means[conds_levels], pch =10, col ="black")# Add a solid line connecting the meanslines(x_positions, means[conds_levels], col ="black", lwd =2)# Add horizontal segments at the means (optional, similar to ggplot2's stat_summary)segments( x_positions -0.1, means[conds_levels], x_positions +0.1, means[conds_levels],col ="black", lwd =3.0)# Add mean labels for each conditiontext(x_positions, means[conds_levels] +2, labels =round(means[conds_levels], 2), cex =2.5, col ="black")# Add error bars using arrows() with specified lower and upper bounds# Function to compute standard errorse <-function(x) sd(x, na.rm =TRUE) /sqrt(sum(!is.na(x)))# Get standard errors for each conditionses <-tapply(MU_data$mean_MU, MU_data$condsFile, se)# Get means again, just to be suremeans <-tapply(MU_data$mean_MU, MU_data$condsFile, mean)# Define bounds for error barslower_bounds <- means[conds_levels] -2*ses[conds_levels]upper_bounds <- means[conds_levels] +2*ses[conds_levels]# Add vertical error bars using arrows()for (i in1:length(x_positions)) {arrows(x0 = x_positions[i], y0 = lower_bounds[i], x1 = x_positions[i], y1 = upper_bounds[i], length =0.1, angle =90, code =3, col ="#D55E00", lwd =3.5 )}
Age plots
par(mfrow =c(1, 2))# Define the levels of condsFileconds_levels <-c("No-Delay", "Long-Delay", "One-shot")# Define colors for each conditioncolors <-c("#0072B2", "#D55E00", "#009E73")# Create an empty plotplot(NA, xlim =range(study_time$age), ylim =c(0, 15), # Adjusted y-axis rangexlab ="Age", ylab ="Study time (seconds)",main ="",cex.lab =1.6, # Axis labels (xlab, ylab)cex.axis =1.5, # Tick labelscex.main =1.2# Title)# Add points and trend lines for each conditionfor (i in1:length(conds_levels)) {# Filter data for the current condition condition_data <- study_time[study_time$condsFile == conds_levels[i], ]# Add pointspoints(condition_data$age, condition_data$mean_StudyTime, col =adjustcolor(colors[i], alpha.f =0.4), pch =16)# Add a trend line (linear regression line)abline(lm(mean_StudyTime ~ age, data = condition_data), col = colors[i], lwd =2)}# Add a legend to the plotlegend("topright", legend = conds_levels, col = colors, lty =1, lwd =2, pch =16)# MU age ---------------# Define the levels of condsFileconds_levels <-c("No-Delay", "Long-Delay", "One-shot")# Define colors for each conditioncolors <-c("#0072B2", "#D55E00", "#009E73")# Create an empty plotplot(NA, xlim =range(MU_data$age), ylim =c(-5, 10), # Adjusted y-axis rangexlab ="Age", ylab ="Memory usage (items)",main ="",cex.lab =1.6, # Axis labels (xlab, ylab)cex.axis =1.5, # Tick labelscex.main =1.2# Title)# Add points and trend lines for each conditionfor (i in1:length(conds_levels)) {# Filter data for the current condition condition_data <- MU_data[MU_data$condsFile == conds_levels[i], ]# Add pointspoints(condition_data$age, condition_data$mean_MU, col =adjustcolor(colors[i], alpha.f =0.4), pch =16)# Add a trend line (linear regression line)abline(lm(mean_MU ~ age, data = condition_data), col = colors[i], lwd =2)}# Add a legend to the plotlegend("topright", legend = conds_levels, col = colors, lty =1, lwd =2, pch =16)
Exploratory analyses
Wilcoxon paired t-tests
# Rename values in the 'condsFile' columnfreeResponseOnly$condsFile <-as.character(freeResponseOnly$condsFile)freeResponseOnly$condsFile[freeResponseOnly$condsFile =="No-Delay"] <-"noDelay"freeResponseOnly$condsFile[freeResponseOnly$condsFile =="Long-Delay"] <-"longDelay"# MU firts, we need to make the data in wide formatwide_data <- freeResponseOnly %>%select(participant, condsFile, mean_MU) %>%pivot_wider(names_from = condsFile, values_from = mean_MU)# Run the testwilcox.test(wide_data$noDelay, wide_data$longDelay, paired =TRUE, alternative ="two.sided")
Wilcoxon signed rank test with continuity correction
data: wide_data$noDelay and wide_data$longDelay
V = 704.5, p-value = 0.3334
alternative hypothesis: true location shift is not equal to 0
# Study time, make it wide formatwide_data_ST <- freeResponseOnly %>%select(participant, condsFile, mean_StudyTime) %>%pivot_wider(names_from = condsFile, values_from = mean_StudyTime)# Run the testwilcox.test(wide_data_ST$noDelay, wide_data_ST$longDelay, paired =TRUE, alternative ="two.sided")
Wilcoxon signed rank test with continuity correction
data: wide_data_ST$noDelay and wide_data_ST$longDelay
V = 767, p-value = 0.0008375
alternative hypothesis: true location shift is not equal to 0
# Free V Total, make it widewide_data_FvT <- freeVtotal %>%select(participant, condType, mean_MU) %>%pivot_wider(names_from = condType, values_from = mean_MU)# Run the testwilcox.test(wide_data_FvT$Free, wide_data_FvT$Total, paired =TRUE, alternative ="two.sided")
Wilcoxon signed rank test with continuity correction
data: wide_data_FvT$Free and wide_data_FvT$Total
V = 1089.5, p-value = 0.2813
alternative hypothesis: true location shift is not equal to 0
Metacognition questions
# Set WD if working locallysetwd("D:/Canna_d/EM5_stuff/EM5_April_2025")# Read in datametacog <-read.csv("metacog_EM52.csv",header=TRUE)# Only get participants who were included in analysesmetacog_d <- metacog[metacog$Participant %in% freeResponseOnly$participant, ]# Get tables for kids responses# Q: Which game did you think was harder?metaSum <-cbind(harder=table(metacog_d$Harder_clean)) %>%data.frame()# Q: When the store was closing, did the game get harder?metaSumClosing <-cbind(Closing=table(metacog_d$Closing_harder_clean)) %>%data.frame()# Q: When the store was closing, did you feel like you were guessing or not?metaSumGuess <-cbind(Guess =table(metacog_d$Guess_clean)) %>%data.frame()# Run binomial tests on answersharderTest <-binom.test(metaSum$harder[2],sum(metaSum$harder),0.5)closingTest <-binom.test(metaSumClosing$Closing[2],sum(metaSumClosing$Closing),0.5)guessTest <-binom.test(metaSumGuess$Guess[2],sum(metaSumGuess$Guess),0.5)
Order effects
Have to do preprocessing again:
# Average over all trials for each condition, for each child, as per preregistrationsummarized_data <- data %>%group_by(participant, condsFile, order) %>%summarize(mean_MU =mean(meanMU, na.rm =TRUE),mean_StudyTime =mean(meanListTime, na.rm =TRUE),mean_Streak =mean(meanCorBefInc, na.rm =TRUE),age =first(Age),.groups ='drop')# make sure condition and order is a factorsummarized_data$condsFile <-as.factor(summarized_data$condsFile)summarized_data$order <-as.factor(summarized_data$order)# Remove closing trialsfreeResponseOnly <- summarized_data %>%filter(!(condsFile %in%c("noDelayClosing", "longDelayClosing")))
Order effects: study time
# Run modelstudyTimeOrder <-glmer(mean_StudyTime ~ condsFile + order + (1|participant), data = freeResponseOnly, family =inverse.gaussian(link ="identity"))# Check summarysummary(studyTimeOrder)
Generalized linear mixed model fit by maximum likelihood (Laplace
Approximation) [glmerMod]
Family: inverse.gaussian ( identity )
Formula: mean_StudyTime ~ condsFile + order + (1 | participant)
Data: freeResponseOnly
AIC BIC logLik deviance df.resid
619.4 634.4 -304.7 609.4 144
Scaled residuals:
Min 1Q Median 3Q Max
-1.7848 -0.5443 -0.0570 0.4411 2.2386
Random effects:
Groups Name Variance Std.Dev.
participant (Intercept) 2.94471 1.7160
Residual 0.02327 0.1525
Number of obs: 149, groups: participant, 75
Fixed effects:
Estimate Std. Error t value Pr(>|z|)
(Intercept) 6.1911 0.3725 16.619 < 0.0000000000000002 ***
condsFile1 0.3143 0.1084 2.901 0.00372 **
order1 0.3252 0.2957 1.100 0.27135
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Correlation of Fixed Effects:
(Intr) cndsF1
condsFile1 -0.002
order1 -0.035 -0.038
# Run modelMU_order <-glmer(mean_MU ~ condsFile + order + (1|participant),data = freeResponseOnly, family =gaussian(link ="identity"))
Warning in glmer(mean_MU ~ condsFile + order + (1 | participant), data =
freeResponseOnly, : calling glmer() with family=gaussian (identity link) as a
shortcut to lmer() is deprecated; please call lmer() directly
# Check summarysummary(MU_order)
Linear mixed model fit by REML ['lmerMod']
Formula: mean_MU ~ condsFile + order + (1 | participant)
Data: freeResponseOnly
REML criterion at convergence: 439.7
Scaled residuals:
Min 1Q Median 3Q Max
-2.0393 -0.5121 -0.1910 0.3967 4.3142
Random effects:
Groups Name Variance Std.Dev.
participant (Intercept) 0.3046 0.5520
Residual 0.8131 0.9017
Number of obs: 149, groups: participant, 75
Fixed effects:
Estimate Std. Error t value
(Intercept) 1.72121 0.09762 17.632
condsFile1 0.12392 0.07394 1.676
order1 0.13014 0.09762 1.333
Correlation of Fixed Effects:
(Intr) cndsF1
condsFile1 0.006
order1 0.008 -0.006
# Compare null with fullMUOrder_null <-glmer(mean_MU ~1+ (1|participant), data = freeResponseOnly, family =gaussian(link ="identity"))
Warning in glmer(mean_MU ~ 1 + (1 | participant), data = freeResponseOnly, :
calling glmer() with family=gaussian (identity link) as a shortcut to lmer() is
deprecated; please call lmer() directly
Whether or not performance decreases over time. Doesn’t seem to.
# Make sure trial is a factordata$trial <-as.factor(data$trial)# Order B, no delay firstorderB <- data[data$order =="B",]orderB <- orderB %>%filter(!(condsFile %in%c("noDelayClosing", "longDelayClosing")))ggplot(orderB, aes(x =factor(trial), y = meanListTime)) +geom_boxplot() +facet_wrap(~ condsFile) +labs(x ="Trial", y ="Study Time", title ="Study Time by Trial and Condition, order B") +theme_minimal()
ggplot(orderB, aes(x =factor(trial), y = meanMU)) +geom_boxplot() +facet_wrap(~ condsFile) +labs(x ="Trial", y ="MU", title ="MU by Trial and Condition, order B") +theme_minimal()
# Order D, long delay firstorderD <- data[data$order =="D",]orderD <- orderD %>%filter(!(condsFile %in%c("noDelayClosing", "longDelayClosing")))ggplot(orderD, aes(x =factor(trial), y = meanListTime)) +geom_boxplot() +facet_wrap(~ condsFile) +labs(x ="Trial", y ="Study Time", title ="Study Time by Trial and Condition, order D") +theme_minimal()
ggplot(orderD, aes(x =factor(trial), y = meanMU)) +geom_boxplot() +facet_wrap(~ condsFile) +labs(x ="Trial", y ="MU", title ="MU by Trial and Condition, order D") +theme_minimal()
Block effects model
Marginally significant (only study time) but would not survive corrections for multiple testing.
# Remove closing trialsdata_noClosing <- data %>%filter(!(condsFile %in%c("noDelayClosing", "longDelayClosing")))# Run model for study timestudyTime_block <-glmer(meanListTime ~ condsFile + trial + (1|participant), data = data_noClosing, family =inverse.gaussian(link ="identity"))# Check summarysummary(studyTime_block)
Generalized linear mixed model fit by maximum likelihood (Laplace
Approximation) [glmerMod]
Family: inverse.gaussian ( identity )
Formula: meanListTime ~ condsFile + trial + (1 | participant)
Data: data_noClosing
AIC BIC logLik deviance df.resid
2011.7 2036.3 -999.9 1999.7 439
Scaled residuals:
Min 1Q Median 3Q Max
-1.5077 -0.6487 -0.1901 0.3335 3.6372
Random effects:
Groups Name Variance Std.Dev.
participant (Intercept) 2.36244 1.5370
Residual 0.04854 0.2203
Number of obs: 445, groups: participant, 75
Fixed effects:
Estimate Std. Error t value Pr(>|z|)
(Intercept) 6.25143 0.36220 17.260 < 0.0000000000000002 ***
condsFile1 0.29200 0.09687 3.014 0.00258 **
trial1 0.28631 0.13428 2.132 0.03298 *
trial2 -0.12617 0.11904 -1.060 0.28920
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Correlation of Fixed Effects:
(Intr) cndsF1 trial1
condsFile1 -0.009
trial1 0.038 -0.101
trial2 -0.015 0.054 -0.546
## MU# Run model for MUMU_block <-glmer(meanMU ~ condsFile + trial + (1|participant),data = data_noClosing, family =gaussian(link ="identity"))
Warning in glmer(meanMU ~ condsFile + trial + (1 | participant), data =
data_noClosing, : calling glmer() with family=gaussian (identity link) as a
shortcut to lmer() is deprecated; please call lmer() directly
# Check summarysummary(MU_block)
Linear mixed model fit by REML ['lmerMod']
Formula: meanMU ~ condsFile + trial + (1 | participant)
Data: data_noClosing
REML criterion at convergence: 1627.8
Scaled residuals:
Min 1Q Median 3Q Max
-3.9222 -0.4627 -0.0730 0.4501 5.1315
Random effects:
Groups Name Variance Std.Dev.
participant (Intercept) 0.396 0.6293
Residual 1.950 1.3964
Number of obs: 445, groups: participant, 75
Fixed effects:
Estimate Std. Error t value
(Intercept) 1.71746 0.09837 17.460
condsFile1 0.12190 0.06630 1.839
trial1 -0.03359 0.09352 -0.359
trial2 -0.07386 0.09352 -0.790
Correlation of Fixed Effects:
(Intr) cndsF1 trial1
condsFile1 0.010
trial1 -0.002 -0.004
trial2 -0.002 -0.004 -0.496
# Compare null with fullMU_null <-glmer(meanMU ~1+ (1|participant), data = data_noClosing, family =gaussian(link ="identity"))
Warning in glmer(meanMU ~ 1 + (1 | participant), data = data_noClosing, :
calling glmer() with family=gaussian (identity link) as a shortcut to lmer() is
deprecated; please call lmer() directly
MUfreeAov <-cbind(car::Anova(MU_block),r.squaredGLMM(MU_block,MU_null))# Check p valuesMUfreeAov
# Only look at Closing trialstotalResponseOnly <- summarized_data %>%filter((condsFile %in%c("noDelayClosing", "longDelayClosing")))# Look at distirbutionhist(totalResponseOnly$mean_MU)
# Run modelMUtotal_GLMM <-glmer(mean_MU ~ condsFile + (1|participant),data = totalResponseOnly, family =gaussian(link ="identity"))
Warning in glmer(mean_MU ~ condsFile + (1 | participant), data =
totalResponseOnly, : calling glmer() with family=gaussian (identity link) as a
shortcut to lmer() is deprecated; please call lmer() directly
# No errors etc. It says this is an lmer, truee# Could be better 6/6plot(density(totalResponseOnly$mean_MU), xlim=c(-50, 50), ylim=c(0, 0.6), main='M_1 y_hat')lines(density(predict(MUtotal_GLMM, type='response') ), col='red')
# somewhat ok 6/6plot(MUtotal_GLMM)
# The qq plot is beautiful 6/6residuals <-residuals(MUtotal_GLMM)qqnorm(residuals)qqline(residuals, col ="red")
# This model fits great 6/6check_model(MUtotal_GLMM)
MUfree_null <-glmer(mean_MU ~1+ (1|participant), data = totalResponseOnly, family =gaussian(link ="identity"))
Warning in glmer(mean_MU ~ 1 + (1 | participant), data = totalResponseOnly, :
calling glmer() with family=gaussian (identity link) as a shortcut to lmer() is
deprecated; please call lmer() directly
MUfreeAov <-cbind(car::Anova(MUtotal_GLMM),r.squaredGLMM(MUtotal_GLMM,MUfree_null))# The total model fits better 6/6anova(MUfree_null,MUtotal_GLMM)
# No delay has less MU but it is non-significant!summary(MUtotal_GLMM)
Linear mixed model fit by REML ['lmerMod']
Formula: mean_MU ~ condsFile + (1 | participant)
Data: totalResponseOnly
REML criterion at convergence: 800.6
Scaled residuals:
Min 1Q Median 3Q Max
-2.08868 -0.51808 0.00402 0.61783 2.18411
Random effects:
Groups Name Variance Std.Dev.
participant (Intercept) 2.262 1.504
Residual 10.617 3.258
Number of obs: 149, groups: participant, 75
Fixed effects:
Estimate Std. Error t value
(Intercept) 1.9914 0.3186 6.250
condsFile1 0.6047 0.2671 2.264
Correlation of Fixed Effects:
(Intr)
condsFile1 0.007
# Add columns to say if its long/no delay or free/total responsesummarized_data$Delay <-ifelse(grepl("longDelay", summarized_data$condsFile), "long", "no")summarized_data$Response <-ifelse(grepl("Closing", summarized_data$condsFile), "Total", "Free")# Make sure they're factorssummarized_data$Delay <-factor(summarized_data$Delay)summarized_data$Response <-factor(summarized_data$Response)# Now fit the interaction modelMU_interaction <-lmer(mean_MU ~ Delay + Response + Delay*Response + (1|participant), data = summarized_data)# good 6/6plot(density(summarized_data$mean_MU), xlim=c(-50, 50), ylim=c(0, 0.6), main='M_1 y_hat')lines(density(predict(MU_interaction, type='response') ), col='red')
# somewhat ok 6/6plot(MU_interaction)
# The qq plot is not good 6/6residuals <-residuals(MU_interaction)qqnorm(residuals)qqline(residuals, col ="red")
# This model fits horrible 6/6check_model(MU_interaction)
MUfree_null <-lmer(mean_MU ~1+ (1|participant), data = summarized_data)MUfreeAov <-cbind(car::Anova(MU_interaction),r.squaredGLMM(MU_interaction,MUfree_null))# The total model fits better 6/6anova(MUfree_null,MU_interaction)
NOTE: Results may be misleading due to involvement in interactions
Pair <-summary(pairs(Emm,adjust="holm"))Pair
contrast estimate SE df t.ratio p.value
long - no 0.73 0.282 222 2.584 0.0104
Results are averaged over the levels of: Response
Degrees-of-freedom method: kenward-roger
# responseEmm <-emmeans(MU_interaction,~Response)
NOTE: Results may be misleading due to involvement in interactions
Pair <-summary(pairs(Emm,adjust="holm"))Pair
contrast estimate SE df t.ratio p.value
Free - Total -0.269 0.282 220 -0.955 0.3407
Results are averaged over the levels of: Delay
Degrees-of-freedom method: kenward-roger
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula:
mean_MU ~ Delay * Response + (1 | participant) + (1 | Delay:participant) +
(1 | Response:participant)
Data: summarized_data
REML criterion at convergence: 1420.2
Scaled residuals:
Min 1Q Median 3Q Max
-2.88873 -0.42050 -0.05041 0.36612 3.03416
Random effects:
Groups Name Variance Std.Dev.
Response:participant (Intercept) 0.322785947531 0.56814254
Delay:participant (Intercept) 0.000000002831 0.00005321
participant (Intercept) 0.963311047033 0.98148410
Residual 5.715309898058 2.39067143
Number of obs: 298, groups:
Response:participant, 150; Delay:participant, 149; participant, 75
Fixed effects:
Estimate Std. Error df t value Pr(>|t|)
(Intercept) 1.8559 0.1850 74.3292 10.034 0.00000000000000182 ***
Delay1 0.3648 0.1386 148.1557 2.632 0.00939 **
Response1 -0.1349 0.1461 74.2093 -0.924 0.35863
Delay1:Response1 -0.2394 0.1385 148.2336 -1.728 0.08604 .
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Correlation of Fixed Effects:
(Intr) Delay1 Rspns1
Delay1 0.006
Response1 0.000 0.000
Dly1:Rspns1 0.000 0.000 0.007
optimizer (nloptwrap) convergence code: 0 (OK)
boundary (singular) fit: see help('isSingular')
anova(model)
Type III Analysis of Variance Table with Satterthwaite's method
Sum Sq Mean Sq NumDF DenDF F value Pr(>F)
Delay 39.585 39.585 1 148.156 6.9262 0.009393 **
Response 4.877 4.877 1 74.209 0.8532 0.358631
Delay:Response 17.069 17.069 1 148.234 2.9865 0.086042 .
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
MU(total) in No-delay + Long-delay plot
# Calculate means and standard errorsmeans <-tapply(totalResponseOnly$mean_MU, totalResponseOnly$condsFile, mean)# Calculate standard deviations and sample sizes for each conditionsds <-tapply(totalResponseOnly$mean_MU, totalResponseOnly$condsFile, sd)n_per_condition <-tapply(totalResponseOnly$mean_MU, totalResponseOnly$condsFile, length)# Calculate standard errorsse <- sds /sqrt(n_per_condition)# Define the x-axis levels (to match the ggplot2 ordering)conds_levels <-c("noDelayClosing", "longDelayClosing")x_positions <-1:length(conds_levels)# Create an empty plotplot( x_positions, means[conds_levels], type ="n", xaxt ="n", ylim =c(-5, 10.0), xlim =c(0.5, 2.5),xlab ="", ylab ="Mean Memory Usage (items)", main ="",cex.lab =1.5,cex.axis =1.5,cex.main =1.5)participants <-unique(totalResponseOnly$participant)for (p in participants) { this_participant <- totalResponseOnly[totalResponseOnly$participant == p, ]if (nrow(this_participant) ==2) {# Get the x positions for this participant’s conditions x_vals <-match(this_participant$condsFile, conds_levels) y_vals <- this_participant$mean_MUlines(x_vals, y_vals, col =adjustcolor("#009E73", alpha.f =0.3), lwd =1) }}# Add x-axis labels normallyaxis(1, at = x_positions, labels = conds_levels, cex.axis =1.6)# Add points for each participantfor (i in1:length(conds_levels)) { condition_data <- totalResponseOnly[totalResponseOnly$condsFile == conds_levels[i], ]points(rep(x_positions[i], nrow(condition_data)), condition_data$mean_MU, pch =1, col ="#0072B2")}# Add points for the meanspoints(x_positions, means[conds_levels], pch =10, col ="black")# Add a solid line connecting the meanslines(x_positions, means[conds_levels], col ="black", lwd =2)# Add horizontal segments at the means (optional, similar to ggplot2's stat_summary)segments( x_positions -0.1, means[conds_levels], x_positions +0.1, means[conds_levels],col ="black", lwd =3.0)# Add mean labels for each conditiontext(x_positions, means[conds_levels] +2, labels =round(means[conds_levels], 2), cex =2.5, col ="black")# Add error bars using arrows() with specified lower and upper bounds# Function to compute standard errorse <-function(x) sd(x, na.rm =TRUE) /sqrt(sum(!is.na(x)))# Get standard errors for each conditionses <-tapply(totalResponseOnly$mean_MU, totalResponseOnly$condsFile, se)# Get means again, just to be suremeans <-tapply(totalResponseOnly$mean_MU, totalResponseOnly$condsFile, mean)# Define bounds for error barslower_bounds <- means[conds_levels] -2*ses[conds_levels]upper_bounds <- means[conds_levels] +2*ses[conds_levels]# Add vertical error bars using arrows()for (i in1:length(x_positions)) {arrows(x0 = x_positions[i], y0 = lower_bounds[i], x1 = x_positions[i], y1 = upper_bounds[i], length =0.1, angle =90, code =3, col ="#D55E00", lwd =3.5 )}
Effect size
It can be difficult and/or problematic to compute effect size for mixed models perhaps, but here it goes.
library(emmeans)# Study timeEmm <-emmeans(studyTimeGlmm,~condsFile)Pair <-summary(pairs(Emm,adjust="holm"))Pair
d_MU <-t_to_d(t=Pair$t.ratio,Pair$df,paired =TRUE)# Free V TotalEmm <-emmeans(freeVtotal_glmm,~condType)Pair <-summary(pairs(Emm,adjust="holm"))Pair
contrast estimate SE df t.ratio p.value
Free - Total -0.271 0.29 74 -0.934 0.3534
Degrees-of-freedom method: kenward-roger
d_fVt <-t_to_d(t=Pair$t.ratio,Pair$df,paired =TRUE)# MU interactionEmm <-emmeans(MU_interaction,~Delay)
NOTE: Results may be misleading due to involvement in interactions
Pair <-summary(pairs(Emm,adjust="holm"))Pair
contrast estimate SE df t.ratio p.value
long - no 0.73 0.282 222 2.584 0.0104
Results are averaged over the levels of: Response
Degrees-of-freedom method: kenward-roger
NOTE: Results may be misleading due to involvement in interactions
Pair <-summary(pairs(Emm,adjust="holm"))Pair
contrast estimate SE df t.ratio p.value
Free - Total -0.269 0.282 220 -0.955 0.3407
Results are averaged over the levels of: Delay
Degrees-of-freedom method: kenward-roger
d_fVt <-t_to_d(t=Pair$t.ratio,Pair$df,paired =TRUE)Emm <-emmeans(MU_interaction, ~ Response * Delay)# This creates the interaction contrasts (difference of differences)int_contrast <-contrast(Emm, interaction ="pairwise", adjust ="holm")int_sum <-summary(int_contrast)d_int <-t_to_d(t = int_sum$t.ratio[1], df = int_sum$df[1], paired =TRUE)