Reading Tests

Z-scores

Word reading

# 1. Create group M and SD values by class (time, errors and number of syllables)
df %>% 
  mutate(
    group_time_mean = case_when(
      class == 1 ~ 92.88, 
      class == 2 ~ 90.29, 
      class == 3 ~ 65.39,
      class == 4 ~ 62, 
      class == 5 ~ 61.26,
      class == "uni" ~ 77.17, 
    ),
    group_time_sd = case_when(
      class == 1 ~ 18.7, 
      class == 2 ~ 19.13, 
      class == 3 ~ 14.4,
      class == 4 ~ 12.65, 
      class == 5 ~ 11.73, 
      class == "uni" ~ 16.99
    ),
    group_error_mean = case_when(
      class == 1 ~ 4.8, 
      class == 2 ~ 4.66, 
      class == 3 ~ 2.32, 
      class == 4 ~ 1.77, 
      class == 5 ~ 1.77,
      class == "uni" ~ 2.23
    ),
    group_error_sd = case_when(
      class == 1 ~ 3.04, 
      class == 2 ~ 3.11, 
      class == 3 ~ 2.57, 
      class == 4 ~ 1.7, 
      class == 5 ~ 1.79,
      class == "uni" ~ 2.25
    ),
    group_syl_mean = case_when(
      class == 1 ~ 3.95, 
      class == 2 ~ 4.08, 
      class == 3 ~ 4.91, 
      class == 4 ~ 5.16, 
      class == 5 ~ 5.21, 
      class == "uni" ~ 4.77
    ),
    group_syl_sd = case_when(
      class == 1~ 0.83, 
      class == 2 ~ 0.88, 
      class == 3 ~ 0.98, 
      class == 4 ~ 0.99, 
      class == 5 ~ 0.97,
      class == "uni" ~ 1.02
    ),
    syl_n_wr = case_when(
      # syllable count: 352 syllables 
      class == 1 ~ 353, 
      class == 2 ~ 353, 
      # syllable count: 56 syllables 2 lists + 98 syllables 2 lists (308)
      class == 3 ~ 308, 
      class == 4 ~ 308, 
      class == 5 ~ 308,
      class == "uni" ~ 352
    ), 
    wr_syl = syl_n_wr/wr_time
    )-> df 


# create z scores: (groupM - subjM)/groupSD

df %>% 
  mutate(
    wr_time_z = (group_time_mean - wr_time)/group_time_sd,
    wr_time_z = round(wr_time_z,2),
    
    wr_error_z = (group_error_mean - wr_errors)/group_error_sd,
    wr_error_z = round(wr_error_z,2),
    
    wr_syl_z = (group_syl_mean - wr_syl)/group_syl_sd,
    wr_syl_z = round(wr_syl_z,2)
  ) %>% 
  
  # remove group values
  
  dplyr::select(ID:AoO, wr_time:nwr_errors, wr_syl, wr_time_z:wr_syl_z) -> df

Nonword reading

# 1. Create group M and SD values by class (time, errors and number of syllables)
df %>% 
  mutate(
    group_time_mean = case_when(
      class == 1 ~ 77.91, 
      class == 2 ~ 75.51, 
      class == 3 ~ 57.07,
      class == 4 ~ 55.68, 
      class == 5 ~ 54.98,
      class == "uni" ~ 63.22 
    ),
    group_time_sd = case_when(
      class == 1 ~ 20.57, 
      class == 2 ~ 18.62, 
      class == 3 ~ 13.51,
      class == 4 ~ 12.43, 
      class == 5 ~ 11.62, 
      class == "uni" ~ 15.98
    ),
    group_error_mean = case_when(
      class == 1 ~ 4.66, 
      class == 2 ~ 4.84, 
      class == 3 ~ 3.16, 
      class == 4 ~ 2.9, 
      class == 5 ~ 2.67,
      class == "uni" ~ 3.14
    ),
    group_error_sd = case_when(
      class == 1 ~ 3.68, 
      class == 2 ~ 3.76, 
      class == 3 ~ 2.84, 
      class == 4 ~ 2.53, 
      class == 5 ~ 2.49,
      class == "uni" ~ 2.66
    ),
    group_syl_mean = case_when(
      class == 1 ~ 2.4, 
      class == 2 ~ 2.46, 
      class == 3 ~ 2.84, 
      class == 4 ~ 2.9, 
      class == 5 ~ 2.92, 
      class == "uni" ~ 2.96
    ),
    group_syl_sd = case_when(
      class == 1 ~ 0.57, 
      class == 2 ~ 0.56, 
      class == 3 ~ 0.62, 
      class == 4 ~ 0.61, 
      class == 5 ~ 0.6,
      class == "uni" ~ 0.76
    ),
    syl_n_nwr = case_when(
      # syllable count: 176 syllables 
      class == 1 ~ 176, 
      class == 2 ~ 176, 
      # syllable count: 56 list 1 + 98 list 2 = 154 
      class == 3 ~ 154, 
      class == 4 ~ 154, 
      class == 5 ~ 154,
      class == "uni" ~ 176
    ), 
    nwr_syl = syl_n_nwr/nwr_time
  ) -> df 

# create z scores: (groupM - subjM)/groupDS

df %>% 
  mutate(
    nwr_time_z = (group_time_mean - nwr_time)/group_time_sd,
    nwr_error_z = (group_error_mean - nwr_errors)/group_error_sd,
    nwr_syl_z = (group_syl_mean - nwr_syl)/group_syl_sd
  ) %>% 
  mutate(across(nwr_time_z:nwr_syl_z, ~ round(.x,2))) %>% 
  # remove group values 
  dplyr::select(ID:AoO, wr_time:wr_syl_z, nwr_syl:nwr_syl_z) -> df 

Identify poor readers

# Exclusion criteria for TD 

df %>% 
  mutate(
    # reading time <= -2sd from mean -> exclude 
  cr_wr_time = case_when(
    group == "DYS" ~ "DYS",
    group == "TD" & wr_time_z <= -2 ~ "PR",
    group == "TD" & wr_time_z > -2 ~ "TD"
  ),
  cr_nwr_time = case_when(
    group == "YES" ~ "DYS",
    group == "TD" & nwr_time_z <= -2 ~ "PR",
    group == "TD" & nwr_time_z > -2 ~ "TD"
  ),
  cr_wr_error = case_when(
    group == "DYS" ~ "DYS", 
    group == "TD" & wr_error_z <= -2 ~ "PR", 
    group == "TD" & wr_error_z > -2 ~ "TD"
  ),
  cr_nwr_error = case_when(
    group == "DYS" ~ "DYS", 
    group == "TD" & nwr_error_z <= -2 ~ "PR", 
    group == "TD" & nwr_error_z > -2 ~ "TD"
  )) -> df 


df %>%
  group_by(ID) %>% 
  rowwise() %>% 
  mutate(group.exclusion = case_when(
    group == "DYS" ~ "DYS",
    group == "TD" & sum(cr_wr_time %in% c("PR"), 
                            cr_nwr_time %in% c("PR"), 
                            cr_wr_error %in% c("PR"), 
                            cr_nwr_error %in% c("PR")) >= 2 ~ "PR",
    group == "TD" & sum(cr_wr_time %in% c("PR"), 
                            cr_nwr_time %in% c("PR"), 
                            cr_wr_error %in% c("PR"), 
                            cr_nwr_error %in% c("PR")) < 2 ~ "TD",
    TRUE ~ NA_character_
  )) %>% 
  ungroup() -> df 

# df %>%
#   filter(group.exclusion == "PR") %>%
#   dplyr::select(ID, group, wr_time_z, wr_error_z, wr_syl_z, nwr_time_z, nwr_error_z, nwr_syl_z) %>%
#   kable(caption = "Poor readers without diagnosis (stricter criteria)") %>% kable_styling()
# 
# df %>% 
#   rowwise() %>% 
#   relocate(nwr_time_z, .after = wr_error_z) %>% relocate(nwr_error_z, .after = nwr_time_z) %>% 
#   mutate(reading.score = mean(c_across(wr_time_z:nwr_error_z)), 
#          reading.score = round(reading.score, 2)) %>% 
#   dplyr::select(ID, group, reading.score) %>% 
#   filter(group == "TD" & reading.score < -2) %>% 
#   kable(caption = "Poor readers without diagnosis (less strict criteria)") %>% kable_styling()

df %>% 
  filter(group.exclusion == "PR") %>% 
  dplyr::select(ID, group, fdp_wr_time, fdp_wr_error, fdp_nwr_time, fdp_nwr_error) %>% 
  kable(caption = "Poor readers (CRR = Criterio completamente raggiunto, PS = Prestazione sufficiente, RA = Richiesta attenzione, RII = Richiesta intervento immediato)") %>% kable_styling()
Poor readers (CRR = Criterio completamente raggiunto, PS = Prestazione sufficiente, RA = Richiesta attenzione, RII = Richiesta intervento immediato)
ID group fdp_wr_time fdp_wr_error fdp_nwr_time fdp_nwr_error
LAE23 TD RII PS RII PS
LAE38 TD RII PS RII RA
LC19 TD RII PS RII PS
MEN02 TD RII RA RII RII
MEN10 TD RII PS RII PS
MEN29 TD RII RII PS RII
MEN35 TD PS RII CRR RII

Exclude participants

df %>%
  dplyr::select(ID, group, wr_time_z, wr_error_z, nwr_time_z, nwr_error_z, group.exclusion) %>%
  rowwise() %>%
  mutate(reading.score = mean(c_across(wr_time_z:nwr_error_z)),
         reading.score = round(reading.score,2)) %>%
  ungroup() %>%

  mutate(
    exclude = case_when(

      ID == "MEN12" ~ 1, # discalculia - 3rd - TD
      ID == "MEN18" ~ 1, # disgrafia, discalculia - 3rd - TD
      ID == "MEN26" ~ 1, # disgrafia - 5th - TD
      ID == "LAE33" ~ 1, # disgrafia, disortografia, 3rd - TD

      TRUE ~ 0
    )
  ) %>%

  ### exclude
  filter(exclude == 0) %>%
  filter(!startsWith(ID, "VER")) %>%

  ### other exclusion criteria! 
  # filter(group.exclusion == "DYS" | (group.exclusion == "TD")) %>%
  # filter(group == "DYS" | (group == "TD" & reading.score > -2)) %>%
  
  dplyr::select(-exclude) -> df


### check sample 
df %>%
  summarize(
    n = n(), .by = "group"
  ) %>% 
  kable(caption = "Final sample") %>% kable_styling()
Final sample
group n
DYS 29
TD 57

Descriptive Statistics

Real word time (z) by group
group mean sd range
DYS -4.15 2.49 -14.12
DYS -4.15 2.49 -0.58
TD -0.71 1.21 -4.97
TD -0.71 1.21 1.65
Real word errors (z) by group
group mean sd range
DYS -2.75 2.58 -9.07
DYS -2.75 2.58 1.04
TD -0.01 0.83 -2.36
TD -0.01 0.83 1.18
Nonwords time (z) by group
group mean sd range
DYS -3.03 1.93 -8.35
DYS -3.03 1.93 -0.44
TD -0.34 1.18 -4.58
TD -0.34 1.18 1.80
Nonwords time (z) by group
group mean sd range
DYS -3.04 3.05 -11.78
DYS -3.04 3.05 0.75
TD -0.29 1.32 -4.55
TD -0.29 1.32 1.29

Inferential Statistics

Differences by groups in word reading performance

lm(wr_time_z ~ group, data = df)-> wr.time
lm(wr_error_z ~ group, data = df) -> wr.error

tab_model(wr.time, wr.error)
  wr time z wr error z
Predictors Estimates CI p Estimates CI p
(Intercept) -4.15 -4.80 – -3.51 <0.001 -2.75 -3.35 – -2.15 <0.001
group [TD] 3.44 2.65 – 4.24 <0.001 2.74 2.00 – 3.49 <0.001
Observations 86 86
R2 / R2 adjusted 0.471 / 0.465 0.392 / 0.385
Word reading time: Predicted values
Group Estimate SE CI
DYS -4.15 0.32 -4.8 - -3.51
TD -0.71 0.23 -1.17 - -0.25
Word reading time
Sum Sq Df F value Pr(>F)
group 227.98 1 74.77 0
Residuals 256.11 84 NA NA
AIC AICc BIC R2 R2_adjusted RMSE Sigma
343.9051 344.1978 351.2682 0.4709468 0.4646486 1.725688 1.746112
Word reading errors: Predicted values
Group Estimate SE CI
DYS -2.75 0.30 -3.35 - -2.15
TD -0.01 0.22 -0.44 - 0.42
Word reading errors
Sum Sq Df F value Pr(>F)
group 144.67 1 54.13 0
Residuals 224.50 84 NA NA
AIC AICc BIC R2 R2_adjusted RMSE Sigma
332.5781 332.8708 339.9412 0.3918814 0.3846419 1.615705 1.634826

Differences by groups in nonword reading performance

lm(nwr_time_z ~ group, data = df) -> nwr.time
lm(nwr_error_z ~ group, data = df) -> nwr.error

tab_model(nwr.time, nwr.error)
  nwr time z nwr error z
Predictors Estimates CI p Estimates CI p
(Intercept) -3.03 -3.58 – -2.49 <0.001 -3.04 -3.80 – -2.28 <0.001
group [TD] 2.69 2.02 – 3.36 <0.001 2.75 1.81 – 3.69 <0.001
Observations 86 86
R2 / R2 adjusted 0.432 / 0.425 0.289 / 0.280
Nonword reading time: Predicted values
Group Estimate SE CI
DYS -3.03 0.27 -3.58 - -2.49
TD -0.34 0.20 -0.73 - 0.05
Nonword reading time
Sum Sq Df F value Pr(>F)
group 138.90 1 63.78 0
Residuals 182.94 84 NA NA
AIC AICc BIC R2 R2_adjusted RMSE Sigma
314.9707 315.2634 322.3338 0.4315857 0.4248188 1.458492 1.475753
Nonword reading errors: Predicted values
Group Estimate SE CI
DYS -3.04 0.38 -3.8 - -2.28
TD -0.29 0.27 -0.83 - 0.26
Nonword reading errors
Sum Sq Df F value Pr(>F)
group 145.62 1 34.07 0
Residuals 359.07 84 NA NA
AIC AICc BIC R2 R2_adjusted RMSE Sigma
372.9666 373.2593 380.3297 0.2885322 0.2800623 2.043345 2.067528

Plots