library(readxl)
library(lme4)
## Loading required package: Matrix
library(effects)
## Loading required package: carData
## lattice theme set by effectsTheme()
## See ?effectsTheme for details.
library(car)
library(emmeans)
library(knitr)
library(reshape2)
library(dplyr)
## 
## Attaching package: 'dplyr'
## The following object is masked from 'package:car':
## 
##     recode
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(forcats)
library(DHARMa)
## This is DHARMa 0.4.6. For overview type '?DHARMa'. For recent changes, type news(package = 'DHARMa')
library(Hmisc)
## 
## Attaching package: 'Hmisc'
## The following objects are masked from 'package:dplyr':
## 
##     src, summarize
## The following objects are masked from 'package:base':
## 
##     format.pval, units
library(phia)
library(lsmeans)
## The 'lsmeans' package is now basically a front end for 'emmeans'.
## Users are encouraged to switch the rest of the way.
## See help('transition') for more information, including how to
## convert old 'lsmeans' objects and scripts to work with 'emmeans'.
library(multcomp)
## Loading required package: mvtnorm
## Loading required package: survival
## Loading required package: TH.data
## Loading required package: MASS
## 
## Attaching package: 'MASS'
## The following object is masked from 'package:dplyr':
## 
##     select
## 
## Attaching package: 'TH.data'
## The following object is masked from 'package:MASS':
## 
##     geyser
library(nlme)
## 
## Attaching package: 'nlme'
## The following object is masked from 'package:dplyr':
## 
##     collapse
## The following object is masked from 'package:lme4':
## 
##     lmList
library(lattice)
library(ggplot2)
library(lmerTest)
## 
## Attaching package: 'lmerTest'
## The following object is masked from 'package:lme4':
## 
##     lmer
## The following object is masked from 'package:stats':
## 
##     step
library(stats)
library(fractalRegression)
library(MASS)
library(car)
setwd("C:/Users/Marcel/Desktop/Bachelor Thesis/Data Analysis/Relevant R Scripts/RT Data")
rt <-read_excel("rt_data_cleaned_merged.xlsx")
rt$Block <- factor(rt$Block, ordered = TRUE, levels = c('1','2','3','4','5','6','7','8','9','10'))
rt$Subject <- as.factor(rt$Subject)
rt$Trial <- as.numeric(rt$Trial)
str(rt)
## tibble [66,240 × 8] (S3: tbl_df/tbl/data.frame)
##  $ Subject  : Factor w/ 23 levels "6","11","12",..: 1 1 1 1 1 1 1 1 1 1 ...
##  $ Block    : Ord.factor w/ 10 levels "1"<"2"<"3"<"4"<..: 1 1 1 1 1 1 1 1 1 1 ...
##  $ Step     : num [1:66240] 1 2 3 4 5 6 1 2 3 4 ...
##  $ Step.ACC : num [1:66240] 1 1 1 1 1 1 1 1 1 1 ...
##  $ RT       : num [1:66240] 646 1252 554 2384 641 ...
##  $ Trial.ACC: num [1:66240] 1 1 1 1 1 1 1 1 1 1 ...
##  $ Sequence : num [1:66240] 2 2 2 2 2 2 2 2 2 2 ...
##  $ Trial    : num [1:66240] 1 1 1 1 1 1 2 2 2 2 ...
###### mean outlier removal

# Calculate block-level mean RT and SD for each subject, based on individual steps
block_stats_mean <- rt %>%
  group_by(Subject, Block) %>%
  summarise(
    BlockMeanRT = mean(RT, na.rm = TRUE),
    BlockSDRT = sd(RT, na.rm = TRUE),
    .groups = 'drop'
  )

# Join block-level stats back to the original dataset
rt_with_block_stats_mean <- rt %>%
  left_join(block_stats_mean, by = c("Subject", "Block"))

# Flag steps as outliers based on the mean and 2.5*SD criterion.
rt_with_block_stats_mean <- rt_with_block_stats_mean %>%
  mutate(Outlier = abs(RT - BlockMeanRT) > 2.5 * BlockSDRT)

# Create a dataset with only the individual outlier steps removed
rt_cleaned_mean_steps <- rt_with_block_stats_mean %>%
  filter(!Outlier) %>%
  dplyr::select(-c(BlockMeanRT, BlockSDRT, Outlier))
# Splitting the dataset into the learning blocks and test blocks
rt_learningblocks <- rt_cleaned_mean_steps %>% 
  filter(Block %in% c("1", "2", "3", "4", "5", "6", "7", "8"))

rt_testblocks <- rt_cleaned_mean_steps %>%
  filter(Block %in% c("9", "10"))
# Calculate the mean step accuracy and mean for Response times for each block for each participant
blockaverage <- rt_learningblocks %>%
  group_by(Subject, Block) %>%
  summarise(MeanStepACC = mean(Step.ACC, na.rm = TRUE),
            MeanRT = mean(RT, na.rm = TRUE)) %>%
  ungroup()
## `summarise()` has grouped output by 'Subject'. You can override using the
## `.groups` argument.
# Plot for mean response times
rt_plot <- ggplot(blockaverage, aes(x = Block, y = MeanRT, group = Subject)) +
  geom_line(aes(color = as.factor(Subject))) +
  facet_wrap(~ Subject, scales = "free_x") +  # Allow free scales on the x-axis only
  labs(title = "A) Participants' Mean Response Time Over Blocks",
       x = "Block",
       y = "Mean Response Time (ms)") +
  theme_minimal() +
  theme(legend.position = "none") +
  ylim(50, 1400)  # Set fixed y-axis limits
print(rt_plot)

# Plot for mean step accuracy
accuracy_plot <- ggplot(blockaverage, aes(x = Block, y = MeanStepACC, group = Subject)) +
  geom_line(aes(color = as.factor(Subject))) +
  facet_wrap(~ Subject, scales = "free_x") +  # Allow free scales on the x-axis only
  labs(title = "B) Participants' Mean Step Accuracy Over Blocks",
       x = "Block",
       y = "Predicted Mean Step Accuracy") +
  theme_minimal() +
  theme(legend.position = "none") +
  ylim(0.7, 1)  # Set fixed y-axis limits
print(accuracy_plot)
## Warning: Removed 1 row containing missing values or values outside the scale range
## (`geom_line()`).

# Fit the linear mixed-effects model for raw response times
model_rt_lmm <- lmer(RT ~ Block + (1 | Subject), data = rt, REML = FALSE)
summary(model_rt_lmm)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
##   method [lmerModLmerTest]
## Formula: RT ~ Block + (1 | Subject)
##    Data: rt
## 
##       AIC       BIC    logLik  deviance  df.resid 
## 1052083.5 1052192.7 -526029.8 1052059.5     66228 
## 
## Scaled residuals: 
##     Min      1Q  Median      3Q     Max 
##  -1.493  -0.301  -0.144   0.102 108.083 
## 
## Random effects:
##  Groups   Name        Variance Std.Dev.
##  Subject  (Intercept)  25231   158.8   
##  Residual             461808   679.6   
## Number of obs: 66240, groups:  Subject, 23
## 
## Fixed effects:
##              Estimate Std. Error        df t value Pr(>|t|)    
## (Intercept)   472.666     33.226    23.000  14.226 6.91e-13 ***
## Block.L      -251.906      8.350 66217.000 -30.169  < 2e-16 ***
## Block.Q       220.624      8.350 66217.000  26.423  < 2e-16 ***
## Block.C      -109.154      8.350 66217.000 -13.073  < 2e-16 ***
## Block^4       138.100      8.350 66217.000  16.540  < 2e-16 ***
## Block^5       -36.720      8.350 66217.000  -4.398 1.10e-05 ***
## Block^6        37.519      8.350 66217.000   4.494 7.02e-06 ***
## Block^7       -17.512      8.350 66217.000  -2.097    0.036 *  
## Block^8        11.007      8.350 66217.000   1.318    0.187    
## Block^9         2.675      8.350 66217.000   0.320    0.749    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Correlation of Fixed Effects:
##         (Intr) Blck.L Blck.Q Blck.C Blck^4 Blck^5 Blck^6 Blck^7 Blck^8
## Block.L 0.000                                                         
## Block.Q 0.000  0.000                                                  
## Block.C 0.000  0.000  0.000                                           
## Block^4 0.000  0.000  0.000  0.000                                    
## Block^5 0.000  0.000  0.000  0.000  0.000                             
## Block^6 0.000  0.000  0.000  0.000  0.000  0.000                      
## Block^7 0.000  0.000  0.000  0.000  0.000  0.000  0.000               
## Block^8 0.000  0.000  0.000  0.000  0.000  0.000  0.000  0.000        
## Block^9 0.000  0.000  0.000  0.000  0.000  0.000  0.000  0.000  0.000
# Obtain effects of the RT model
effects_rt <- allEffects(model_rt_lmm)
df_rt <- as.data.frame(effects_rt[[1]])
df_rt$l83 <- df_rt$fit - 1.3722 * df_rt$se
df_rt$u83 <- df_rt$fit + 1.3722 * df_rt$se

base_size <- 14
ggplot(df_rt, aes(x = Block, y = fit)) +
  geom_errorbar(aes(ymin = l83, ymax = u83), width = 0.2, size = 1, color = "darkorchid4") +  
  geom_point(color = "darkorchid2", size = 4) +
  geom_vline(xintercept = 8.5, color = "red", size = 1) +  
  xlab("Block") + ylab("RT(ms)") +
  ggtitle("A) RT ~ Block") +
  theme_minimal() +
  theme(text = element_text(size = base_size),  
        axis.title = element_text(size = base_size + 2), 
        plot.title = element_text(size = base_size + 4, face = "bold"),  
        axis.text = element_text(size = base_size - 2),
        axis.text.y = element_text(face = "bold"),
        axis.text.x = element_text(face = "bold"))    
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

# Fit a logistic generalized mixed-effects model for binary step accuracy
model_acc <- glmer(Step.ACC ~ Block + (1 | Subject), data = rt, family = binomial(link = "logit"))
summary(model_acc)
## Generalized linear mixed model fit by maximum likelihood (Laplace
##   Approximation) [glmerMod]
##  Family: binomial  ( logit )
## Formula: Step.ACC ~ Block + (1 | Subject)
##    Data: rt
## 
##      AIC      BIC   logLik deviance df.resid 
##  27399.7  27499.8 -13688.8  27377.7    66229 
## 
## Scaled residuals: 
##     Min      1Q  Median      3Q     Max 
## -7.7604  0.1750  0.2118  0.2560  0.7081 
## 
## Random effects:
##  Groups  Name        Variance Std.Dev.
##  Subject (Intercept) 0.2215   0.4706  
## Number of obs: 66240, groups:  Subject, 23
## 
## Fixed effects:
##             Estimate Std. Error z value Pr(>|z|)    
## (Intercept)  2.98254    0.10000  29.825  < 2e-16 ***
## Block.L      0.02700    0.05112   0.528   0.5974    
## Block.Q     -0.95787    0.05073 -18.883  < 2e-16 ***
## Block.C      0.26578    0.05313   5.002 5.66e-07 ***
## Block^4     -0.53388    0.05589  -9.553  < 2e-16 ***
## Block^5      0.12688    0.05700   2.226   0.0260 *  
## Block^6     -0.13493    0.05901  -2.287   0.0222 *  
## Block^7      0.11390    0.06000   1.898   0.0577 .  
## Block^8      0.08343    0.05953   1.401   0.1611    
## Block^9     -0.01478    0.06006  -0.246   0.8056    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Correlation of Fixed Effects:
##         (Intr) Blck.L Blck.Q Blck.C Blck^4 Blck^5 Blck^6 Blck^7 Blck^8
## Block.L -0.004                                                        
## Block.Q -0.042  0.036                                                 
## Block.C  0.010 -0.298  0.026                                          
## Block^4 -0.021  0.069 -0.218  0.005                                   
## Block^5  0.005 -0.105  0.059 -0.122 -0.046                            
## Block^6 -0.005  0.038 -0.053  0.007 -0.088 -0.046                     
## Block^7  0.005  0.001 -0.001 -0.054  0.001 -0.027 -0.039              
## Block^8  0.005  0.014 -0.029 -0.009 -0.017  0.001  0.006 -0.022       
## Block^9 -0.001  0.011  0.014 -0.024 -0.017  0.015  0.017 -0.012 -0.038
# Obtain effects of the accuracy model
effects_acc <- allEffects(model_acc)
df_acc <- as.data.frame(effects_acc[[1]])
df_acc$l83 <- df_acc$fit - 1.3722 * df_acc$se
df_acc$u83 <- df_acc$fit + 1.3722 * df_acc$se

# Plot effects for Step Accuracy with error bars
ggplot(df_acc, aes(x = Block, y = fit)) +
  geom_errorbar(aes(ymin = l83, ymax = u83), width = 0.2, size = 1, color = "aquamarine4") +  
  geom_point(color = "aquamarine3", size = 4) +
  geom_vline(xintercept = 8.5, color = "red", size = 1) +  
  xlab("Block") + ylab("Step Accuracy (%)") +
  ggtitle("B) Step.ACC ~ Block") +
  theme_minimal() +
  theme(text = element_text(size = base_size),  
        axis.title = element_text(size = base_size + 2), 
        plot.title = element_text(size = base_size + 4, face = "bold"),  
        axis.text = element_text(size = base_size - 2),
        axis.text.y = element_text(face = "bold"),
        axis.text.x = element_text(face = "bold"))     

Anova(model_rt_lmm)
Anova(model_acc)
# Post hocs model RT
emm_blocks <- emmeans(model_rt_lmm, specs = ~ Block)
## Note: D.f. calculations have been disabled because the number of observations exceeds 3000.
## To enable adjustments, add the argument 'pbkrtest.limit = 66240' (or larger)
## [or, globally, 'set emm_options(pbkrtest.limit = 66240)' or larger];
## but be warned that this may result in large computation time and memory use.
## Note: D.f. calculations have been disabled because the number of observations exceeds 3000.
## To enable adjustments, add the argument 'lmerTest.limit = 66240' (or larger)
## [or, globally, 'set emm_options(lmerTest.limit = 66240)' or larger];
## but be warned that this may result in large computation time and memory use.
comparisons <- pairs(emm_blocks)
print(comparisons)
##  contrast         estimate   SE  df z.ratio p.value
##  Block1 - Block2    327.84 11.8 Inf  27.763  <.0001
##  Block1 - Block3    355.98 11.8 Inf  30.146  <.0001
##  Block1 - Block4    380.00 11.8 Inf  32.181  <.0001
##  Block1 - Block5    388.17 11.8 Inf  32.873  <.0001
##  Block1 - Block6    388.86 11.8 Inf  32.931  <.0001
##  Block1 - Block7    412.49 11.8 Inf  34.932  <.0001
##  Block1 - Block8    431.55 11.8 Inf  36.546  <.0001
##  Block1 - Block9    442.75 11.8 Inf  37.495  <.0001
##  Block1 - Block10   366.19 11.8 Inf  31.011  <.0001
##  Block2 - Block3     28.14 11.8 Inf   2.383  0.3360
##  Block2 - Block4     52.16 11.8 Inf   4.417  0.0004
##  Block2 - Block5     60.33 11.8 Inf   5.109  <.0001
##  Block2 - Block6     61.02 11.8 Inf   5.167  <.0001
##  Block2 - Block7     84.65 11.8 Inf   7.169  <.0001
##  Block2 - Block8    103.71 11.8 Inf   8.783  <.0001
##  Block2 - Block9    114.91 11.8 Inf   9.731  <.0001
##  Block2 - Block10    38.35 11.8 Inf   3.248  0.0386
##  Block3 - Block4     24.02 11.8 Inf   2.034  0.5745
##  Block3 - Block5     32.19 11.8 Inf   2.726  0.1631
##  Block3 - Block6     32.88 11.8 Inf   2.785  0.1416
##  Block3 - Block7     56.51 11.8 Inf   4.786  0.0001
##  Block3 - Block8     75.57 11.8 Inf   6.400  <.0001
##  Block3 - Block9     86.77 11.8 Inf   7.348  <.0001
##  Block3 - Block10    10.21 11.8 Inf   0.865  0.9974
##  Block4 - Block5      8.17 11.8 Inf   0.692  0.9996
##  Block4 - Block6      8.86 11.8 Inf   0.750  0.9992
##  Block4 - Block7     32.49 11.8 Inf   2.752  0.1534
##  Block4 - Block8     51.55 11.8 Inf   4.366  0.0005
##  Block4 - Block9     62.75 11.8 Inf   5.314  <.0001
##  Block4 - Block10   -13.81 11.8 Inf  -1.169  0.9769
##  Block5 - Block6      0.69 11.8 Inf   0.058  1.0000
##  Block5 - Block7     24.32 11.8 Inf   2.060  0.5563
##  Block5 - Block8     43.38 11.8 Inf   3.674  0.0090
##  Block5 - Block9     54.58 11.8 Inf   4.622  0.0002
##  Block5 - Block10   -21.98 11.8 Inf  -1.861  0.6955
##  Block6 - Block7     23.63 11.8 Inf   2.001  0.5981
##  Block6 - Block8     42.69 11.8 Inf   3.615  0.0112
##  Block6 - Block9     53.89 11.8 Inf   4.564  0.0002
##  Block6 - Block10   -22.67 11.8 Inf  -1.920  0.6556
##  Block7 - Block8     19.06 11.8 Inf   1.614  0.8417
##  Block7 - Block9     30.26 11.8 Inf   2.562  0.2357
##  Block7 - Block10   -46.30 11.8 Inf  -3.921  0.0035
##  Block8 - Block9     11.20 11.8 Inf   0.948  0.9948
##  Block8 - Block10   -65.36 11.8 Inf  -5.535  <.0001
##  Block9 - Block10   -76.56 11.8 Inf  -6.483  <.0001
## 
## Degrees-of-freedom method: asymptotic 
## P value adjustment: tukey method for comparing a family of 10 estimates
# Post hocs model acc
emm_blocks <- emmeans(model_acc, specs = ~ Block)
comparisons <- pairs(emm_blocks)
print(comparisons)
##  contrast         estimate     SE  df z.ratio p.value
##  Block1 - Block2  -1.08505 0.0722 Inf -15.034  <.0001
##  Block1 - Block3  -1.12648 0.0731 Inf -15.403  <.0001
##  Block1 - Block4  -1.06307 0.0717 Inf -14.832  <.0001
##  Block1 - Block5  -1.13033 0.0732 Inf -15.434  <.0001
##  Block1 - Block6  -1.02738 0.0709 Inf -14.486  <.0001
##  Block1 - Block7  -0.94929 0.0693 Inf -13.705  <.0001
##  Block1 - Block8  -1.05945 0.0716 Inf -14.798  <.0001
##  Block1 - Block9  -0.83683 0.0670 Inf -12.491  <.0001
##  Block1 - Block10 -0.33417 0.0590 Inf  -5.665  <.0001
##  Block2 - Block3  -0.04143 0.0866 Inf  -0.478  1.0000
##  Block2 - Block4   0.02197 0.0854 Inf   0.257  1.0000
##  Block2 - Block5  -0.04528 0.0867 Inf  -0.522  1.0000
##  Block2 - Block6   0.05767 0.0848 Inf   0.680  0.9996
##  Block2 - Block7   0.13576 0.0834 Inf   1.627  0.8352
##  Block2 - Block8   0.02559 0.0854 Inf   0.300  1.0000
##  Block2 - Block9   0.24822 0.0816 Inf   3.043  0.0711
##  Block2 - Block10  0.75088 0.0751 Inf   9.992  <.0001
##  Block3 - Block4   0.06341 0.0862 Inf   0.735  0.9993
##  Block3 - Block5  -0.00385 0.0875 Inf  -0.044  1.0000
##  Block3 - Block6   0.09910 0.0856 Inf   1.157  0.9785
##  Block3 - Block7   0.17720 0.0842 Inf   2.104  0.5247
##  Block3 - Block8   0.06703 0.0862 Inf   0.778  0.9989
##  Block3 - Block9   0.28965 0.0824 Inf   3.515  0.0160
##  Block3 - Block10  0.79232 0.0761 Inf  10.418  <.0001
##  Block4 - Block5  -0.06726 0.0863 Inf  -0.779  0.9989
##  Block4 - Block6   0.03569 0.0844 Inf   0.423  1.0000
##  Block4 - Block7   0.11379 0.0830 Inf   1.371  0.9361
##  Block4 - Block8   0.00362 0.0849 Inf   0.043  1.0000
##  Block4 - Block9   0.22624 0.0811 Inf   2.789  0.1400
##  Block4 - Block10  0.72891 0.0747 Inf   9.762  <.0001
##  Block5 - Block6   0.10295 0.0857 Inf   1.201  0.9724
##  Block5 - Block7   0.18104 0.0843 Inf   2.147  0.4941
##  Block5 - Block8   0.07088 0.0862 Inf   0.822  0.9983
##  Block5 - Block9   0.29350 0.0825 Inf   3.558  0.0137
##  Block5 - Block10  0.79616 0.0762 Inf  10.452  <.0001
##  Block6 - Block7   0.07809 0.0823 Inf   0.948  0.9948
##  Block6 - Block8  -0.03207 0.0843 Inf  -0.380  1.0000
##  Block6 - Block9   0.19055 0.0805 Inf   2.368  0.3451
##  Block6 - Block10  0.69321 0.0740 Inf   9.371  <.0001
##  Block7 - Block8  -0.11017 0.0829 Inf  -1.329  0.9472
##  Block7 - Block9   0.11246 0.0790 Inf   1.423  0.9203
##  Block7 - Block10  0.61512 0.0724 Inf   8.499  <.0001
##  Block8 - Block9   0.22262 0.0811 Inf   2.746  0.1554
##  Block8 - Block10  0.72529 0.0746 Inf   9.724  <.0001
##  Block9 - Block10  0.50266 0.0702 Inf   7.161  <.0001
## 
## Results are given on the log odds ratio (not the response) scale. 
## P value adjustment: tukey method for comparing a family of 10 estimates