Effects of Interactive and Hands-on Learning Experience of Assistive Technology on College Students’ Perspectives and Knowledge

Published

February 24, 2026

This website contains R code used for the analyses in Park et al. (in press). The scripts were also posted through an online data repository at Center for Open Science and GitHub.

Park, J., Gremp, M., & Shin, M. (in press). Effects of interactive and hands-on learning experience of assistive technology on college students’ perspectives and knowledge. Education and Information Technologies.

Code
suppressPackageStartupMessages({
  library(stringr)
  library(scales)
  library(reshape2)
  library(gtsummary)
  library(flextable)
  library(purrr)
  library(ggeffects)
  library(ggplot2)
  library(dplyr)
  library(ordinal)
  library(texreg)
  library(MASS)
  library(nlme)
  library(tidyr)
})

load("data/AT-college.RData")

Demographic Profiles of Participants

df$group <- as.factor(df$group)

demo_tbl <- df %>%
  mutate(group = case_when(
    group == "1" ~ "Treatment",
    group == "0" ~ "Control"
  )) %>%
  filter(time == "0") %>%
  dplyr::select(group, gender, year, college) %>%
  tbl_summary(by = group,
              percent = "column") 

demo_tbl_ft <- as_flex_table(demo_tbl)
demo_tbl_ft 

Characteristic

Control
N = 501

Treatment
N = 641

gender

female

37 (74%)

49 (77%)

male

9 (18%)

12 (19%)

not_reported

0 (0%)

1 (1.6%)

third

4 (8.0%)

2 (3.1%)

year

freshman

38 (76%)

40 (63%)

junior

1 (2.0%)

6 (9.4%)

sophomore

11 (22%)

18 (28%)

college

business

1 (2.0%)

0 (0%)

education_AHS

39 (78%)

39 (61%)

health_science

3 (6.0%)

5 (7.8%)

justice_safety_military

0 (0%)

1 (1.6%)

letter_art_Social_Science

6 (12%)

16 (25%)

STEM

1 (2.0%)

3 (4.7%)

1n (%)

Code
reverse_thresholds <- function(data) {
  
  sum <- summary(data)
  
  cf <- as.data.frame(sum$coefficients)
  
  cf[1:4, 1] <- cf[1:4, 1] * -1
  cf[1:4, 3] <- cf[1:4, 3] * -1
  
  rownames(cf)[1:4] <- c("intercept (Y>1)", "intercept (Y>2)", "intercept (Y>3)", "intercept (Y>4)")
  
  return(cf)
}

reverse_thresholds_alt <- function(data) {
  
  sum <- summary(data)
  
  cf <- as.data.frame(sum$coefficients)
  
  cf[1:3, 1] <- cf[1:3, 1] * -1
  cf[1:3, 3] <- cf[1:3, 2] * -1
  
  rownames(cf)[1:3] <- c("intercept (Y>2)", "intercept (Y>3)", "intercept (Y>4)")
  
  return(cf)
}

Main Effects (SP)

SP1

df$SP1 <- as.factor(df$SP1)

main.SP1 <- clmm(SP1 ~ group + time + group:time +
                    (1 | student), data = df, Hess=TRUE, nAGQ=7)
cf <- reverse_thresholds(main.SP1)

cf %>% mutate(odd_ratio = exp(Estimate)) %>% 
  mutate_if(is.numeric, ~ round(., 2))
                Estimate Std. Error z value Pr(>|z|) odd_ratio
intercept (Y>1)     5.21       0.87    5.98     0.00    183.76
intercept (Y>2)     4.49       0.71    6.35     0.00     88.87
intercept (Y>3)     2.10       0.44    4.80     0.00      8.13
intercept (Y>4)     0.22       0.36    0.61     0.54      1.25
group1             -0.11       0.47   -0.23     0.82      0.90
time                0.49       0.43    1.13     0.26      1.64
group1:time         1.30       0.62    2.09     0.04      3.67

SP2

df$SP2 <- as.factor(df$SP2)

main.SP2 <- clmm(SP2 ~ group + time + group:time +
                    (1 | student), data = df, Hess=TRUE, nAGQ=7)
cf <- reverse_thresholds_alt(main.SP2)

cf %>% mutate(odd_ratio = exp(Estimate)) %>% 
  mutate_if(is.numeric, ~ round(., 2))
                Estimate Std. Error z value Pr(>|z|) odd_ratio
intercept (Y>2)     4.73       0.75   -0.75     0.00    113.77
intercept (Y>3)     1.85       0.41   -0.41     0.00      6.38
intercept (Y>4)    -0.22       0.36   -0.36     0.55      0.81
group1              0.06       0.46    0.13     0.90      1.06
time                0.61       0.43    1.43     0.15      1.85
group1:time         1.10       0.60    1.84     0.07      3.01

SP3

df$SP3 <- as.factor(df$SP3)

main.SP3 <- clmm(SP3 ~ group + time + group:time +
                    (1 | student), data = df, Hess=TRUE, nAGQ=7)
cf <- reverse_thresholds(main.SP3)

cf %>% mutate(odd_ratio = exp(Estimate)) %>% 
  mutate_if(is.numeric, ~ round(., 2))
                Estimate Std. Error z value Pr(>|z|) odd_ratio
intercept (Y>1)     4.79       0.69    6.99     0.00    119.74
intercept (Y>2)     4.12       0.59    6.97     0.00     61.58
intercept (Y>3)     1.66       0.40    4.18     0.00      5.27
intercept (Y>4)     0.29       0.36    0.82     0.41      1.34
group1             -0.60       0.47   -1.28     0.20      0.55
time               -0.27       0.41   -0.65     0.52      0.77
group1:time         1.41       0.58    2.44     0.01      4.09

SP4

df$SP4 <- as.factor(df$SP4)

main.SP4 <- clmm(SP4 ~ group + time + group:time +
                    (1 | student), data = df, Hess=TRUE, nAGQ=7)
cf <- reverse_thresholds(main.SP4)

cf %>% mutate(odd_ratio = exp(Estimate)) %>% 
  mutate_if(is.numeric, ~ round(., 2))
                Estimate Std. Error z value Pr(>|z|) odd_ratio
intercept (Y>1)     5.26       0.73    7.21     0.00    192.46
intercept (Y>2)     3.85       0.54    7.12     0.00     47.22
intercept (Y>3)     1.09       0.39    2.81     0.01      2.98
intercept (Y>4)    -0.97       0.38   -2.52     0.01      0.38
group1             -0.18       0.49   -0.37     0.71      0.84
time               -0.22       0.39   -0.56     0.57      0.80
group1:time         0.67       0.54    1.24     0.21      1.94

SP5

df$SP5 <- as.factor(df$SP5)

main.SP5 <- clmm(SP5 ~ group + time + group:time +
                    (1 | student), data = df, Hess=TRUE, nAGQ=7)
cf <- reverse_thresholds(main.SP5)

cf %>% mutate(odd_ratio = exp(Estimate)) %>% 
  mutate_if(is.numeric, ~ round(., 2))
                Estimate Std. Error z value Pr(>|z|) odd_ratio
intercept (Y>1)     4.46       0.60    7.49     0.00     86.58
intercept (Y>2)     1.38       0.37    3.73     0.00      3.96
intercept (Y>3)    -1.05       0.36   -2.92     0.00      0.35
intercept (Y>4)    -3.09       0.45   -6.82     0.00      0.05
group1             -0.38       0.45   -0.85     0.39      0.68
time               -0.28       0.38   -0.74     0.46      0.75
group1:time         1.04       0.52    1.99     0.05      2.82

SP6

df$SP6 <- as.factor(df$SP6)

main.SP6 <- clmm(SP6 ~ group + time + group:time +
                    (1 | student), data = df, Hess=TRUE, nAGQ=7)
cf <- reverse_thresholds(main.SP6)

cf %>% mutate(odd_ratio = exp(Estimate)) %>% 
  mutate_if(is.numeric, ~ round(., 2))
                Estimate Std. Error z value Pr(>|z|) odd_ratio
intercept (Y>1)     5.66       0.75    7.52     0.00    286.62
intercept (Y>2)     3.86       0.57    6.76     0.00     47.60
intercept (Y>3)     1.15       0.44    2.61     0.01      3.16
intercept (Y>4)    -0.76       0.43   -1.75     0.08      0.47
group1             -0.44       0.56   -0.80     0.43      0.64
time               -0.05       0.40   -0.12     0.91      0.95
group1:time         0.55       0.55    1.00     0.32      1.73

SP7

df$SP7 <- as.factor(df$SP7)

main.SP7 <- clmm(SP7 ~ group + time + group:time +
                    (1 | student), data = df, Hess=TRUE, nAGQ=7)
cf <- reverse_thresholds(main.SP7)

cf %>% mutate(odd_ratio = exp(Estimate)) %>% 
  mutate_if(is.numeric, ~ round(., 2))
                Estimate Std. Error z value Pr(>|z|) odd_ratio
intercept (Y>1)     4.92       0.73    6.73     0.00    137.60
intercept (Y>2)     4.26       0.65    6.58     0.00     70.72
intercept (Y>3)     2.33       0.46    5.06     0.00     10.23
intercept (Y>4)     0.28       0.37    0.74     0.46      1.32
group1             -0.76       0.49   -1.55     0.12      0.47
time                0.25       0.42    0.61     0.54      1.29
group1:time         1.81       0.62    2.91     0.00      6.10

SP8

df$SP8 <- as.factor(df$SP8)

main.SP8 <- clmm(SP8 ~ group + time + group:time +
                    (1 | student), data = df, Hess=TRUE, nAGQ=7)
cf <- reverse_thresholds(main.SP8)

cf %>% mutate(odd_ratio = exp(Estimate)) %>% 
  mutate_if(is.numeric, ~ round(., 2))
                Estimate Std. Error z value Pr(>|z|) odd_ratio
intercept (Y>1)     3.10       0.51    6.10     0.00     22.22
intercept (Y>2)     0.01       0.39    0.04     0.97      1.01
intercept (Y>3)    -4.02       0.59   -6.83     0.00      0.02
intercept (Y>4)    -6.10       0.94   -6.49     0.00      0.00
group1             -0.25       0.51   -0.48     0.63      0.78
time                0.68       0.41    1.64     0.10      1.97
group1:time        -1.17       0.56   -2.07     0.04      0.31
screenreg(list(main.SP1, main.SP2, main.SP3, main.SP4, main.SP5, main.SP6, main.SP7, main.SP8), 
          custom.model.names = c("SP 1", "SP 2", "SP 3", "SP 4", "SP 5", "SP 6", "SP 7", "SP 8"))

======================================================================================================================================
                                SP 1         SP 2         SP 3         SP 4         SP 5         SP 6         SP 7         SP 8       
--------------------------------------------------------------------------------------------------------------------------------------
group1                            -0.11         0.06        -0.60        -0.18        -0.38        -0.44        -0.76        -0.25    
                                  (0.47)       (0.46)       (0.47)       (0.49)       (0.45)       (0.56)       (0.49)       (0.51)   
time                               0.49         0.61        -0.27        -0.22        -0.28        -0.05         0.25         0.68    
                                  (0.43)       (0.43)       (0.41)       (0.39)       (0.38)       (0.40)       (0.42)       (0.41)   
group1:time                        1.30 *       1.10         1.41 *       0.67         1.04 *       0.55         1.81 **     -1.17 *  
                                  (0.62)       (0.60)       (0.58)       (0.54)       (0.52)       (0.55)       (0.62)       (0.56)   
1|2                               -5.21 ***                 -4.79 ***    -5.26 ***    -4.46 ***    -5.66 ***    -4.92 ***    -3.10 ***
                                  (0.87)                    (0.69)       (0.73)       (0.60)       (0.75)       (0.73)       (0.51)   
2|3                               -4.49 ***    -4.73 ***    -4.12 ***    -3.85 ***    -1.38 ***    -3.86 ***    -4.26 ***    -0.01    
                                  (0.71)       (0.75)       (0.59)       (0.54)       (0.37)       (0.57)       (0.65)       (0.39)   
3|4                               -2.10 ***    -1.85 ***    -1.66 ***    -1.09 **      1.05 **     -1.15 **     -2.33 ***     4.02 ***
                                  (0.44)       (0.41)       (0.40)       (0.39)       (0.36)       (0.44)       (0.46)       (0.59)   
4|5                               -0.22         0.22        -0.29         0.97 *       3.09 ***     0.76        -0.28         6.10 ***
                                  (0.36)       (0.36)       (0.36)       (0.38)       (0.45)       (0.43)       (0.37)       (0.94)   
--------------------------------------------------------------------------------------------------------------------------------------
Log Likelihood                  -205.36      -214.11      -252.19      -282.25      -301.08      -287.26      -228.83      -250.23    
AIC                              426.71       442.22       520.38       580.51       618.16       590.52       473.66       516.45    
BIC                              454.15       466.23       547.82       607.94       645.59       617.95       501.10       543.89    
Num. obs.                        228          228          228          228          228          228          228          228       
Groups (student)                 114          114          114          114          114          114          114          114       
Variance: student: (Intercept)     1.65         1.82         1.82         2.77         2.05         4.36         2.30         3.17    
======================================================================================================================================
*** p < 0.001; ** p < 0.01; * p < 0.05

Main Effects (PK)

PK1

df$PK1 <- as.factor(df$PK1)

main.PK1 <- clmm(PK1 ~ group + time + group:time +
                    (1 | student), data = df, Hess=TRUE, nAGQ=7)
cf <- reverse_thresholds(main.PK1)

cf %>% mutate(odd_ratio = exp(Estimate)) %>% 
  mutate_if(is.numeric, ~ round(., 2))
                Estimate Std. Error z value Pr(>|z|) odd_ratio
intercept (Y>1)     1.36       0.34    4.06     0.00      3.91
intercept (Y>2)    -1.30       0.34   -3.86     0.00      0.27
intercept (Y>3)    -3.86       0.49   -7.83     0.00      0.02
intercept (Y>4)    -6.19       0.68   -9.06     0.00      0.00
group1              0.20       0.40    0.51     0.61      1.23
time                0.88       0.40    2.20     0.03      2.41
group1:time         3.02       0.59    5.08     0.00     20.43

PK2

df$PK2 <- as.factor(df$PK2)

main.PK2 <- clmm(PK2 ~ group + time + group:time +
                    (1 | student), data = df, Hess=TRUE, nAGQ=7)
cf <- reverse_thresholds(main.PK2)

cf %>% mutate(odd_ratio = exp(Estimate)) %>% 
  mutate_if(is.numeric, ~ round(., 2))
                Estimate Std. Error z value Pr(>|z|) odd_ratio
intercept (Y>1)     0.29       0.31    0.96     0.34      1.34
intercept (Y>2)    -1.63       0.35   -4.68     0.00      0.20
intercept (Y>3)    -3.60       0.45   -7.99     0.00      0.03
intercept (Y>4)    -5.92       0.63   -9.45     0.00      0.00
group1              0.64       0.40    1.61     0.11      1.90
time                1.37       0.40    3.42     0.00      3.92
group1:time         2.05       0.55    3.74     0.00      7.73

PK3

df$PK3 <- as.factor(df$PK3)

main.PK3 <- clmm(PK3 ~ group + time + group:time +
                    (1 | student), data = df, Hess=TRUE, nAGQ=7)
cf <- reverse_thresholds(main.PK3)

cf %>% mutate(odd_ratio = exp(Estimate)) %>% 
  mutate_if(is.numeric, ~ round(., 2))
                Estimate Std. Error z value Pr(>|z|) odd_ratio
intercept (Y>1)     0.60       0.33    1.81     0.07      1.83
intercept (Y>2)    -1.55       0.36   -4.28     0.00      0.21
intercept (Y>3)    -3.75       0.49   -7.73     0.00      0.02
intercept (Y>4)    -6.21       0.68   -9.15     0.00      0.00
group1              0.20       0.42    0.48     0.63      1.23
time                1.23       0.40    3.08     0.00      3.43
group1:time         2.65       0.57    4.64     0.00     14.11

PK4

df$PK4 <- as.factor(df$PK4)

main.PK4 <- clmm(PK4 ~ group + time + group:time +
                    (1 | student), data = df, Hess=TRUE, nAGQ=7)
cf <- reverse_thresholds(main.PK4)

cf %>% mutate(odd_ratio = exp(Estimate)) %>% 
  mutate_if(is.numeric, ~ round(., 2))
                Estimate Std. Error z value Pr(>|z|) odd_ratio
intercept (Y>1)     0.74       0.34    2.18     0.03      2.09
intercept (Y>2)    -1.15       0.35   -3.31     0.00      0.32
intercept (Y>3)    -3.13       0.44   -7.18     0.00      0.04
intercept (Y>4)    -5.76       0.63   -9.10     0.00      0.00
group1              0.60       0.43    1.40     0.16      1.82
time                1.06       0.39    2.75     0.01      2.90
group1:time         1.93       0.54    3.56     0.00      6.89

PK5

df$PK5 <- as.factor(df$PK5)

main.PK5 <- clmm(PK5 ~ group + time + group:time +
                    (1 | student), data = df, Hess=TRUE, nAGQ=7)
cf <- reverse_thresholds(main.PK5)

cf %>% mutate(odd_ratio = exp(Estimate)) %>% 
  mutate_if(is.numeric, ~ round(., 2))
                Estimate Std. Error z value Pr(>|z|) odd_ratio
intercept (Y>1)     1.66       0.40    4.14     0.00      5.25
intercept (Y>2)    -0.66       0.37   -1.81     0.07      0.51
intercept (Y>3)    -2.99       0.46   -6.49     0.00      0.05
intercept (Y>4)    -6.07       0.70   -8.68     0.00      0.00
group1              0.32       0.47    0.68     0.50      1.37
time                0.84       0.39    2.16     0.03      2.32
group1:time         2.95       0.59    4.98     0.00     19.18

PK6

df$PK6 <- as.factor(df$PK6)

main.PK6 <- clmm(PK6 ~ group + time + group:time +
                    (1 | student), data = df, Hess=TRUE, nAGQ=7)
cf <- reverse_thresholds(main.PK6)

cf %>% mutate(odd_ratio = exp(Estimate)) %>% 
  mutate_if(is.numeric, ~ round(., 2))
                Estimate Std. Error z value Pr(>|z|) odd_ratio
intercept (Y>1)     0.26       0.30    0.87     0.38      1.30
intercept (Y>2)    -1.73       0.34   -5.02     0.00      0.18
intercept (Y>3)    -3.90       0.47   -8.25     0.00      0.02
intercept (Y>4)    -6.41       0.67   -9.54     0.00      0.00
group1              0.64       0.40    1.61     0.11      1.89
time                1.41       0.40    3.57     0.00      4.11
group1:time         2.29       0.56    4.11     0.00      9.84

PK7

df$PK7 <- as.factor(df$PK7)

main.PK7 <- clmm(PK7 ~ group + time + group:time +
                    (1 | student), data = df, Hess=TRUE, nAGQ=7)
cf <- reverse_thresholds(main.PK7)

cf %>% mutate(odd_ratio = exp(Estimate)) %>% 
  mutate_if(is.numeric, ~ round(., 2))
                Estimate Std. Error z value Pr(>|z|) odd_ratio
intercept (Y>1)     1.27       0.38    3.34     0.00      3.55
intercept (Y>2)    -1.39       0.38   -3.67     0.00      0.25
intercept (Y>3)    -3.66       0.49   -7.42     0.00      0.03
intercept (Y>4)    -6.29       0.70   -8.94     0.00      0.00
group1              0.84       0.46    1.81     0.07      2.31
time                1.13       0.40    2.80     0.01      3.09
group1:time         2.29       0.57    4.03     0.00      9.90
screenreg(list(main.PK1, main.PK2, main.PK3, main.PK4, main.PK5, main.PK6, main.PK7), 
          custom.model.names = c("PK 1", "PK 2", "PK 3", "PK 4", "PK 5", "PK 6", "PK 7"))

=========================================================================================================================
                                PK 1         PK 2         PK 3         PK 4         PK 5         PK 6         PK 7       
-------------------------------------------------------------------------------------------------------------------------
group1                             0.20         0.64         0.20         0.60         0.32         0.64         0.84    
                                  (0.40)       (0.40)       (0.42)       (0.43)       (0.47)       (0.40)       (0.46)   
time                               0.88 *       1.37 ***     1.23 **      1.06 **      0.84 *       1.41 ***     1.13 ** 
                                  (0.40)       (0.40)       (0.40)       (0.39)       (0.39)       (0.40)       (0.40)   
group1:time                        3.02 ***     2.05 ***     2.65 ***     1.93 ***     2.95 ***     2.29 ***     2.29 ***
                                  (0.59)       (0.55)       (0.57)       (0.54)       (0.59)       (0.56)       (0.57)   
1|2                               -1.36 ***    -0.29        -0.60        -0.74 *      -1.66 ***    -0.26        -1.27 ***
                                  (0.34)       (0.31)       (0.33)       (0.34)       (0.40)       (0.30)       (0.38)   
2|3                                1.30 ***     1.63 ***     1.55 ***     1.15 ***     0.66         1.73 ***     1.39 ***
                                  (0.34)       (0.35)       (0.36)       (0.35)       (0.37)       (0.34)       (0.38)   
3|4                                3.86 ***     3.60 ***     3.75 ***     3.13 ***     2.99 ***     3.90 ***     3.66 ***
                                  (0.49)       (0.45)       (0.49)       (0.44)       (0.46)       (0.47)       (0.49)   
4|5                                6.19 ***     5.92 ***     6.21 ***     5.76 ***     6.07 ***     6.41 ***     6.29 ***
                                  (0.68)       (0.63)       (0.68)       (0.63)       (0.70)       (0.67)       (0.70)   
-------------------------------------------------------------------------------------------------------------------------
Log Likelihood                  -261.26      -285.13      -281.08      -298.32      -288.53      -274.59      -283.70    
AIC                              538.52       586.25       578.15       612.64       593.05       565.18       583.41    
BIC                              565.96       613.69       605.59       640.07       620.49       592.61       610.84    
Num. obs.                        228          228          228          228          228          228          228       
Groups (student)                 114          114          114          114          114          114          114       
Variance: student: (Intercept)     0.57         0.54         1.12         1.25         2.19         0.47         1.83    
=========================================================================================================================
*** p < 0.001; ** p < 0.01; * p < 0.05

Main Effects (DK)

main.DK <- glmmPQL(DK ~ group + time + group:time,
                random = ~ 1 | student, data = df, family=poisson)
sum <- summary(main.DK)

cf <- sum$tTable %>% as.data.frame()
cf$Estimate <- cf$Value
cf %>% mutate(irr = exp(Estimate)) %>% 
  mutate_if(is.numeric, ~ round(., 3)) %>%
  dplyr::select(-Value) %>%
  dplyr::select(Estimate, everything()) 
            Estimate Std.Error  DF t-value p-value   irr
(Intercept)    0.565     0.170 112   3.333   0.001 1.760
group1        -0.447     0.249 112  -1.797   0.075 0.640
time           0.393     0.181 112   2.176   0.032 1.481
group1:time    1.555     0.251 112   6.185   0.000 4.735
VarCorr(main.DK)
student = pdLogChol(1) 
            Variance  StdDev   
(Intercept) 0.3767362 0.6137884
Residual    2.0265750 1.4235782
screenreg(list(main.DK), 
          custom.model.names = c("DK Main Effects"))

=====================================
                      DK Main Effects
-------------------------------------
(Intercept)             0.57 **      
                       (0.17)        
group1                 -0.45         
                       (0.25)        
time                    0.39 *       
                       (0.18)        
group1:time             1.55 ***     
                       (0.25)        
-------------------------------------
AIC                                  
BIC                                  
Log Likelihood                       
Num. obs.             228            
Num. groups: student  114            
=====================================
*** p < 0.001; ** p < 0.01; * p < 0.05