1. Pre-processing (for semesters 1 and 2)
# install.packages("devtools")
# devtools::install_github("jrosen48/jmRtools")
Sys.setenv(TZ='America/Detroit')
library(jmRtools)
library(readxl)
library(tidyverse)
library(lubridate)
RR_Course_Data <- read_csv("RR_Course_Data.csv")
CS1 <- read_csv("data/CS1.csv") # this is the pre-survey for the Fall, 2015 and Spring, 2016 semesters
CS1_ss <- dplyr::filter(CS1,
!is.na(Q1MaincellgroupRow1),
opdata_username != "_49147_1",
opdata_username != "_93993_1",
opdata_username != "@X@user.pk_string@X@",
opdata_username != "_80624_1",
opdata_CourseID != "@X@course.course_id@X@",
opdata_username != "") # must revisit
ps12 <- dplyr::arrange(CS1_ss, opdata_username, opdata_CourseID, StartDate)
# ps12$Q1MaincellgroupRow4_rc <- car::recode(ps12$Q1MaincellgroupRow4, "1=5; 2=4; 5=1; 4=2")
ps12$Q1MaincellgroupRow7_rc <- car::recode(ps12$Q1MaincellgroupRow7, "1=5; 2=4; 5=1; 4=2")
ps12$int <- (ps12$Q1MaincellgroupRow1 + ps12$Q1MaincellgroupRow8 + ps12$Q1MaincellgroupRow10+ ps12$Q1MaincellgroupRow5) / 4
ps12$uv <- (ps12$Q1MaincellgroupRow2 + ps12$Q1MaincellgroupRow6+ ps12$Q1MaincellgroupRow9) / 3 # dropped 7 (is this supposed to be dropped 4?)
ps12$percomp <- (ps12$Q1MaincellgroupRow3 + ps12$Q1MaincellgroupRow7_rc) / 2
x <- str_split(ps12$opdata_CourseID, "-")
ps12_f <- mutate(ps12,
subject = map_chr(x, ~ .[1]),
semester = map_chr(x, ~ .[2]),
section = map_chr(x, ~ .[3]))
ps12_f <- select(ps12_f,
student_ID = opdata_username,
course_ID = opdata_CourseID,
subject, semester, section,
int, uv, percomp)
ps12_f <- mutate(ps12_f, student_ID = str_sub(student_ID, start = 2L, end = -3L))
ps12_f <- arrange(ps12_f, student_ID)
CS2 <- read_csv("data/CS2.csv") # this is the pre-survey for the Fall, 2015 and Spring, 2016 semesters
CS2$Q1MaincellgroupRow7_rc <- car::recode(CS2$Q1MaincellgroupRow7, "1=5; 2=4; 5=1; 4=2")
CS2$post_int <- (CS2$Q1MaincellgroupRow1 + CS2$Q1MaincellgroupRow8 + CS2$Q1MaincellgroupRow10+ CS2$Q1MaincellgroupRow5) / 4
CS2$post_uv <- (CS2$Q1MaincellgroupRow2 + CS2$Q1MaincellgroupRow6+ CS2$Q1MaincellgroupRow9) / 3 # dropped 7 (is this supposed to be dropped 4?)
CS2$post_percomp <- (CS2$Q1MaincellgroupRow3 + CS2$Q1MaincellgroupRow7_rc) / 2
CS2$date <- lubridate::ymd_hm(CS2$CompletedDate, tz = "America/Detroit")
CS2 <- arrange(CS2, date)
CS2 <- CS2 %>%
mutate(student_ID = str_sub(opdata_username, start = 2L, end = -3L)) %>%
select(student_ID, contains("post"), date)
CS2 <- CS2[complete.cases(CS2), ]
CS2 <- filter(CS2,
student_ID != "49147",
student_ID != "93993",
student_ID != "80624",
student_ID != "@X@user.pk_string@X@",
student_ID != "@X@course.course_id@X@",
student_ID != "")
CS2 <- distinct(CS2, student_ID, .keep_all = T)
CS2 <- select(CS2, -date)
CS2 <- arrange(CS2, student_ID)
ps12_f <- left_join(ps12_f, CS2, by = "student_ID")
2. Pre-processing (for semester 3)
ps3 <- read_excel("~/Dropbox/1_Research/utility_value_intervention_online_science/CS_1_7_13_17.xls")
ps3$Q1MaincellgroupRow61_rc <- car::recode(ps3$Q1MaincellgroupRow61, "1=5; 2=4; 5=1; 4=2")
# ps3$int <- (ps3$Q1MaincellgroupRow01 + ps3$Q1MaincellgroupRow71 + ps3$Q1MaincellgroupRow91+ ps3$Q1MaincellgroupRow41) / 4
# ps3$uv <- (ps3$Q1MaincellgroupRow11 + ps3$Q1MaincellgroupRow51+ ps3$Q1MaincellgroupRow81) / 3 # dropped 7
# ps3$percomp <- (ps3$Q1MaincellgroupRow21 + ps3$Q1MaincellgroupRow61_rc) / 2
ps3 <- ps3 %>%
mutate(int = composite_mean_maker(ps3, Q1MaincellgroupRow01, Q1MaincellgroupRow71, Q1MaincellgroupRow91, Q1MaincellgroupRow41),
uv = composite_mean_maker(ps3, Q1MaincellgroupRow11, Q1MaincellgroupRow51, Q1MaincellgroupRow81),
percomp = composite_mean_maker(ps3, Q1MaincellgroupRow11, Q1MaincellgroupRow51, Q1MaincellgroupRow81)) %>%
filter(opdata_CourseID != "@X@course.course_id@X@") %>%
separate(opdata_CourseID, c("subject", "semester", "section"), sep = "-", remove = F)
ps3_f <- select(ps3,
student_ID = opdata_username,
course_ID = opdata_CourseID,
subject, semester, section,
int, uv, percomp)
df2 <- read_excel("~/Dropbox/1_Research/utility_value_intervention_online_science/CS_2_7_13_17.xls")
df2$post_int <- (df2$Q2MaincellgroupRow01 + df2$Q2MaincellgroupRow71 + df2$Q2MaincellgroupRow91 + df2$Q2MaincellgroupRow41) / 4
df2$post_uv <- (df2$Q2MaincellgroupRow11 + df2$Q2MaincellgroupRow51+ df2$Q2MaincellgroupRow81) / 3 # dropped 7
df2$post_percomp <- (df2$Q2MaincellgroupRow21)
df2 <- mutate(df2, date = lubridate::mdy_hm(CompletedDate, tz = "America/Detroit"))
df2 <- arrange(df2, date)
df2 <- select(df2, student_ID = opdata_username, contains("post"), date)
df2 <- distinct(df2)
df2 <- select(df2, -date)
pd3_f <- left_join(ps3_f, df2, by = "student_ID")
ps3_f <- mutate(ps3_f,
student_ID = str_sub(student_ID, start = 2, end = -3))
3. Merging and processing merged data
ps12s <- dplyr::select(ps12_f, student_ID, course_ID, subject, semester, section, int, uv, percomp)
ps3s <- dplyr::select(ps3_f, course_ID, subject, semester, section, int, uv, percomp)
x <- bind_rows(ps12s, ps3s)
x <- as_tibble(x)
d <- bind_rows(ps12_f, ps3_f)
# treatment vs. control for sems 1 and 2
# https://docs.google.com/document/d/1g52pl-0JyEO26bFEJ9aE295dL7oZSOU1wrVXvVbd2lg/edit
d <- mutate(d,
intervention_dummy = case_when(
# Fall 15
course_ID == "AnPhA-S116-01" ~ 1,
course_ID == "AnPhA-S116-02" ~ 0,
course_ID == "BioA-S116-01" ~ 1,
course_ID == "BioA-T116-01" ~ 0,
course_ID == "FrScA-S116-01" ~ 1,
course_ID == "FrScA-S116-02" ~ 0,
course_ID == "FrScA-S116-03" ~ 1,
course_ID == "FrScA-S116-04" ~ 0,
course_ID == "FrScA-T116-01" ~ 0,
course_ID == "OcnA-S116-01" ~ 1,
course_ID == "OcnA-S116-01" ~ 0,
course_ID == "OcnA-S116-03" ~ 1,
course_ID == "OcnA-T116-01" ~ 0,
course_ID == "PhysA-S116-01" ~ 1,
course_ID == "PhysA-T116-01" ~ 0,
# Spring 16
course_ID == "AnPhA-S216-01" ~ 0,
course_ID == "AnPhA-S216-02" ~ 1,
course_ID == "BioA-S216-01" ~ 0,
course_ID == "FrScA-S216-01" ~ 0,
course_ID == "FrScA-S216-02" ~ 1,
course_ID == "FrScA-S216-03" ~ 0,
course_ID == "FrScA-S216-04" ~ 1,
course_ID == "OcnA-S216-01" ~ 0,
course_ID == "OcnA-S216-02" ~ 1,
course_ID == "PhysA-S216-01" ~ 0,
# Spring 17
course_ID == "AnPhA-S217-01" ~ 1,
course_ID == "AnPhA-S217-01" ~ 0,
course_ID == "Bio-S217-01" ~ 1,
course_ID == "FrScA-S217-01" ~ 1,
course_ID == "FrScA-S217-02" ~ 0,
course_ID == "FrScA-S217-02." ~ 0,
course_ID == "FrScA-S217-03" ~ 1,
course_ID == "OcnA-S217-01" ~ 0,
course_ID == "OcnA-S217-02" ~ 1,
course_ID == "OcnA-S217-03" ~ 1,
course_ID == "PhysA-S217-01" ~ 0,
TRUE ~ 0
))
d <- rename(d, pre_int = int, pre_uv = uv, pre_percomp = percomp)
4. Processing all gradebook data
x <- read_csv("RR_S3.csv")
x <- select(x, course_ID = Course_ID, student_ID = CU_Pk1, Item_Position:last_access_date)
x <- rename(x, Grade_Category = Grade_Catagory)
RR_Course_Data <- select(RR_Course_Data, course_ID = CourseSectionOrigID, student_ID = Bb_UserPK, Gradebook_Item:last_access_date)
xx <- bind_rows(RR_Course_Data, x)
# write_csv(RR_Course_Data, "s12_gradebook_data.csv")
5. Merging self-report and gradebook data (not run yet)
d$student_ID <- as.character(d$student_ID)
xx$student_ID <- as.character(xx$student_ID)
df <- left_join(d, xx, by = "student_ID")
Processing trace data
library(readxl)
ts_12 <- read_csv("RR_Minutes.csv")
td_12 <- read_csv("RR_Course_Data.csv")
td_3 <- read_excel("Ranelluci Study Data Pull Request.xlsx")
td_12 <- td_12 %>%
select(student_ID = Bb_UserPK, course_ID = CourseSectionOrigID,
gender = Gender, enrollment_reason = EnrollmentReason,
enrollment_status = EnrollmentStatus,
final_grade = FinalGradeCEMS) %>%
distinct()
ts_12 <- ts_12 %>%
select(student_ID = Bb_UserPK,
course_ID = CourseSectionOrigID,
time_spent = TimeSpent)
td_12 <- left_join(td_12, ts_12)
td_3 <- td_3 %>%
select(student_ID = CEMS_Bb_UserPK,
course_ID = Section_ID,
gender = Gender,
enrollment_reason = EnrollmentReason,
enrollment_status = EnrollmentStatus,
final_grade = Final_Grade,
time_spent = `Sum of time spent in course`) %>%
mutate(final_grade = as.numeric(final_grade))
trace_data <- bind_rows(td_12, td_3)
Merging trace data with other data
d$student_ID <- as.integer(d$student_ID)
d <- left_join(d, trace_data)
6. Pre-post analysis
Using multi-level models by course.
60. Looking first at n’s
d %>%
count(intervention_dummy)
## # A tibble: 2 x 2
## intervention_dummy n
## <dbl> <int>
## 1 0 380
## 2 1 429
d[complete.cases(d), ] %>%
count(intervention_dummy)
## # A tibble: 2 x 2
## intervention_dummy n
## <dbl> <int>
## 1 0 8
## 2 1 108
6A. Just looking at pre-post changes in interest and UV and grades
sjPlot::sjt.lmer(lme4::lmer(post_int ~ intervention_dummy + (1 | course_ID), data = d))
|
|
post_int
|
|
|
B
|
CI
|
p
|
Fixed Parts
|
(Intercept)
|
|
4.51
|
3.71 – 5.31
|
<.001
|
intervention_dummy
|
|
-0.85
|
-1.80 – 0.11
|
.096
|
Random Parts
|
σ2
|
|
0.705
|
τ00, course_ID
|
|
0.370
|
Ncourse_ID
|
|
12
|
ICCcourse_ID
|
|
0.344
|
Observations
|
|
121
|
R2 / Ω02
|
|
.262 / .252
|
sjPlot::sjt.lmer(lme4::lmer(post_uv ~ intervention_dummy + (1 | course_ID), data = d))
|
|
post_uv
|
|
|
B
|
CI
|
p
|
Fixed Parts
|
(Intercept)
|
|
3.86
|
3.03 – 4.70
|
<.001
|
intervention_dummy
|
|
-0.72
|
-1.70 – 0.27
|
.166
|
Random Parts
|
σ2
|
|
0.853
|
τ00, course_ID
|
|
0.354
|
Ncourse_ID
|
|
12
|
ICCcourse_ID
|
|
0.293
|
Observations
|
|
121
|
R2 / Ω02
|
|
.205 / .187
|
sjPlot::sjt.lmer(lme4::lmer(final_grade ~ intervention_dummy + (1 | course_ID), data = d))
|
|
final_grade
|
|
|
B
|
CI
|
p
|
Fixed Parts
|
(Intercept)
|
|
76.32
|
73.16 – 79.49
|
<.001
|
intervention_dummy
|
|
1.57
|
-2.78 – 5.91
|
.486
|
Random Parts
|
σ2
|
|
429.987
|
τ00, course_ID
|
|
15.339
|
Ncourse_ID
|
|
36
|
ICCcourse_ID
|
|
0.034
|
Observations
|
|
776
|
R2 / Ω02
|
|
.060 / .051
|
6B. With pre-values added (pre per-comp for final grades)
sjPlot::sjt.lmer(lme4::lmer(post_int ~ pre_int + intervention_dummy + (1 | course_ID), data = d))
|
|
post_int
|
|
|
B
|
CI
|
p
|
Fixed Parts
|
(Intercept)
|
|
1.24
|
0.13 – 2.35
|
.031
|
pre_int
|
|
0.73
|
0.52 – 0.94
|
<.001
|
intervention_dummy
|
|
-0.43
|
-1.06 – 0.21
|
.194
|
Random Parts
|
σ2
|
|
0.535
|
τ00, course_ID
|
|
0.078
|
Ncourse_ID
|
|
12
|
ICCcourse_ID
|
|
0.127
|
Observations
|
|
120
|
R2 / Ω02
|
|
.421 / .420
|
sjPlot::sjt.lmer(lme4::lmer(post_uv ~ pre_uv + intervention_dummy + (1 | course_ID), data = d))
|
|
post_uv
|
|
|
B
|
CI
|
p
|
Fixed Parts
|
(Intercept)
|
|
0.75
|
-0.20 – 1.71
|
.126
|
pre_uv
|
|
0.80
|
0.61 – 0.98
|
<.001
|
intervention_dummy
|
|
-0.22
|
-0.91 – 0.46
|
.525
|
Random Parts
|
σ2
|
|
0.556
|
τ00, course_ID
|
|
0.115
|
Ncourse_ID
|
|
12
|
ICCcourse_ID
|
|
0.172
|
Observations
|
|
118
|
R2 / Ω02
|
|
.457 / .456
|
sjPlot::sjt.lmer(lme4::lmer(final_grade ~ pre_percomp + intervention_dummy + (1 | course_ID), data = d))
|
|
final_grade
|
|
|
B
|
CI
|
p
|
Fixed Parts
|
(Intercept)
|
|
65.40
|
56.73 – 74.06
|
<.001
|
pre_percomp
|
|
2.99
|
0.83 – 5.16
|
.007
|
intervention_dummy
|
|
1.39
|
-3.05 – 5.82
|
.541
|
Random Parts
|
σ2
|
|
429.896
|
τ00, course_ID
|
|
16.048
|
Ncourse_ID
|
|
36
|
ICCcourse_ID
|
|
0.036
|
Observations
|
|
759
|
R2 / Ω02
|
|
.067 / .060
|
6C. With pre-values added + interactions with pre perceived competence
sjPlot::sjt.lmer(lme4::lmer(post_int ~ pre_int + intervention_dummy*pre_percomp + (1 | course_ID), data = d))
|
|
post_int
|
|
|
B
|
CI
|
p
|
Fixed Parts
|
(Intercept)
|
|
1.29
|
-2.32 – 4.91
|
.486
|
pre_int
|
|
0.69
|
0.44 – 0.95
|
<.001
|
intervention_dummy
|
|
-0.58
|
-4.31 – 3.15
|
.761
|
pre_percomp
|
|
0.03
|
-0.88 – 0.93
|
.955
|
intervention_dummy:pre_percomp
|
|
0.04
|
-0.86 – 0.95
|
.926
|
Random Parts
|
σ2
|
|
0.541
|
τ00, course_ID
|
|
0.088
|
Ncourse_ID
|
|
12
|
ICCcourse_ID
|
|
0.140
|
Observations
|
|
120
|
R2 / Ω02
|
|
.425 / .424
|
sjPlot::sjt.lmer(lme4::lmer(post_uv ~ pre_uv + intervention_dummy*pre_percomp + (1 | course_ID), data = d))
|
|
post_uv
|
|
|
B
|
CI
|
p
|
Fixed Parts
|
(Intercept)
|
|
0.72
|
-3.12 – 4.56
|
.715
|
pre_uv
|
|
0.77
|
0.56 – 0.99
|
<.001
|
intervention_dummy
|
|
-0.32
|
-4.23 – 3.59
|
.872
|
pre_percomp
|
|
0.03
|
-0.89 – 0.95
|
.948
|
intervention_dummy:pre_percomp
|
|
0.03
|
-0.92 – 0.98
|
.953
|
Random Parts
|
σ2
|
|
0.564
|
τ00, course_ID
|
|
0.125
|
Ncourse_ID
|
|
12
|
ICCcourse_ID
|
|
0.181
|
Observations
|
|
118
|
R2 / Ω02
|
|
.459 / .458
|
sjPlot::sjt.lmer(lme4::lmer(final_grade ~ pre_uv + intervention_dummy*pre_percomp + (1 | course_ID), data = d))
|
|
final_grade
|
|
|
B
|
CI
|
p
|
Fixed Parts
|
(Intercept)
|
|
64.19
|
51.48 – 76.89
|
<.001
|
pre_uv
|
|
-1.15
|
-3.76 – 1.45
|
.387
|
intervention_dummy
|
|
8.20
|
-8.42 – 24.83
|
.334
|
pre_percomp
|
|
4.52
|
1.07 – 7.97
|
.011
|
intervention_dummy:pre_percomp
|
|
-1.80
|
-6.14 – 2.54
|
.417
|
Random Parts
|
σ2
|
|
427.745
|
τ00, course_ID
|
|
16.074
|
Ncourse_ID
|
|
36
|
ICCcourse_ID
|
|
0.036
|
Observations
|
|
755
|
R2 / Ω02
|
|
.069 / .062
|
6D. With all variables added
sjPlot::sjt.lmer(lme4::lmer(post_uv ~ pre_uv + pre_int + pre_percomp + intervention_dummy + (1 | course_ID), data = d))
|
|
post_uv
|
|
|
B
|
CI
|
p
|
Fixed Parts
|
(Intercept)
|
|
0.54
|
-0.72 – 1.81
|
.400
|
pre_uv
|
|
0.76
|
0.51 – 1.00
|
<.001
|
pre_int
|
|
0.04
|
-0.26 – 0.34
|
.802
|
pre_percomp
|
|
0.05
|
-0.23 – 0.32
|
.750
|
intervention_dummy
|
|
-0.20
|
-0.90 – 0.50
|
.580
|
Random Parts
|
σ2
|
|
0.565
|
τ00, course_ID
|
|
0.118
|
Ncourse_ID
|
|
12
|
ICCcourse_ID
|
|
0.173
|
Observations
|
|
118
|
R2 / Ω02
|
|
.459 / .458
|
sjPlot::sjt.lmer(lme4::lmer(post_int ~ pre_uv + pre_int + pre_percomp + intervention_dummy + (1 | course_ID), data = d))
|
|
post_int
|
|
|
B
|
CI
|
p
|
Fixed Parts
|
(Intercept)
|
|
0.97
|
-0.24 – 2.19
|
.118
|
pre_uv
|
|
0.17
|
-0.07 – 0.41
|
.162
|
pre_int
|
|
0.61
|
0.32 – 0.90
|
<.001
|
pre_percomp
|
|
0.03
|
-0.24 – 0.30
|
.809
|
intervention_dummy
|
|
-0.43
|
-1.08 – 0.22
|
.199
|
Random Parts
|
σ2
|
|
0.532
|
τ00, course_ID
|
|
0.085
|
Ncourse_ID
|
|
12
|
ICCcourse_ID
|
|
0.137
|
Observations
|
|
118
|
R2 / Ω02
|
|
.444 / .443
|
sjPlot::sjt.lmer(lme4::lmer(final_grade ~ pre_uv + pre_int + pre_percomp + intervention_dummy + (1 | course_ID), data = d))
|
|
final_grade
|
|
|
B
|
CI
|
p
|
Fixed Parts
|
(Intercept)
|
|
55.28
|
43.45 – 67.11
|
<.001
|
pre_uv
|
|
-2.92
|
-5.70 – -0.14
|
.040
|
pre_int
|
|
5.78
|
2.48 – 9.08
|
<.001
|
pre_percomp
|
|
2.00
|
-0.83 – 4.84
|
.166
|
intervention_dummy
|
|
1.47
|
-2.95 – 5.88
|
.516
|
Random Parts
|
σ2
|
|
423.048
|
τ00, course_ID
|
|
15.755
|
Ncourse_ID
|
|
36
|
ICCcourse_ID
|
|
0.036
|
Observations
|
|
750
|
R2 / Ω02
|
|
.080 / .076
|
7. Other analyses
sjPlot::sjt.lmer(lme4::lmer(final_grade ~ pre_uv + pre_int + pre_percomp + (1 | course_ID), data = d))
|
|
final_grade
|
|
|
B
|
CI
|
p
|
Fixed Parts
|
(Intercept)
|
|
56.13
|
44.58 – 67.67
|
<.001
|
pre_uv
|
|
-2.98
|
-5.75 – -0.20
|
.036
|
pre_int
|
|
5.82
|
2.52 – 9.11
|
<.001
|
pre_percomp
|
|
2.00
|
-0.83 – 4.84
|
.166
|
Random Parts
|
σ2
|
|
422.661
|
τ00, course_ID
|
|
15.881
|
Ncourse_ID
|
|
36
|
ICCcourse_ID
|
|
0.036
|
Observations
|
|
750
|
R2 / Ω02
|
|
.081 / .076
|
sjPlot::sjt.lmer(lme4::lmer(final_grade ~ I(time_spent/60) + (1 | course_ID), data = d))
|
|
final_grade
|
|
|
B
|
CI
|
p
|
Fixed Parts
|
(Intercept)
|
|
64.66
|
61.38 – 67.93
|
<.001
|
I(time_spent/60)
|
|
0.38
|
0.32 – 0.44
|
<.001
|
Random Parts
|
σ2
|
|
359.037
|
τ00, course_ID
|
|
31.031
|
Ncourse_ID
|
|
36
|
ICCcourse_ID
|
|
0.080
|
Observations
|
|
776
|
R2 / Ω02
|
|
.216 / .214
|
sjPlot::sjt.lmer(lme4::lmer(final_grade ~ pre_uv + pre_int + pre_percomp + I(time_spent/60) + (1 | course_ID), data = d))
|
|
final_grade
|
|
|
B
|
CI
|
p
|
Fixed Parts
|
(Intercept)
|
|
47.11
|
36.15 – 58.07
|
<.001
|
pre_uv
|
|
-3.37
|
-5.98 – -0.76
|
.012
|
pre_int
|
|
5.31
|
2.21 – 8.40
|
<.001
|
pre_percomp
|
|
2.14
|
-0.47 – 4.74
|
.109
|
I(time_spent/60)
|
|
0.37
|
0.31 – 0.43
|
<.001
|
Random Parts
|
σ2
|
|
353.930
|
τ00, course_ID
|
|
30.568
|
Ncourse_ID
|
|
36
|
ICCcourse_ID
|
|
0.080
|
Observations
|
|
750
|
R2 / Ω02
|
|
.235 / .233
|
7A. With gender added
sjPlot::sjt.lmer(lme4::lmer(final_grade ~ pre_uv + pre_int + pre_percomp + gender + (1 | course_ID), data = d))
|
|
final_grade
|
|
|
B
|
CI
|
p
|
Fixed Parts
|
(Intercept)
|
|
60.35
|
48.59 – 72.11
|
<.001
|
pre_uv
|
|
-2.91
|
-5.68 – -0.14
|
.040
|
pre_int
|
|
4.96
|
1.64 – 8.29
|
.004
|
pre_percomp
|
|
2.27
|
-0.54 – 5.08
|
.114
|
gender (M)
|
|
-6.06
|
-9.38 – -2.74
|
<.001
|
Random Parts
|
σ2
|
|
414.508
|
τ00, course_ID
|
|
19.765
|
Ncourse_ID
|
|
36
|
ICCcourse_ID
|
|
0.046
|
Observations
|
|
750
|
R2 / Ω02
|
|
.101 / .097
|
sjPlot::sjt.lmer(lme4::lmer(final_grade ~ I(time_spent/60) + gender + (1 | course_ID), data = d))
|
|
final_grade
|
|
|
B
|
CI
|
p
|
Fixed Parts
|
(Intercept)
|
|
66.77
|
63.27 – 70.26
|
<.001
|
I(time_spent/60)
|
|
0.37
|
0.31 – 0.43
|
<.001
|
gender (M)
|
|
-6.09
|
-9.09 – -3.09
|
<.001
|
Random Parts
|
σ2
|
|
351.239
|
τ00, course_ID
|
|
34.669
|
Ncourse_ID
|
|
36
|
ICCcourse_ID
|
|
0.090
|
Observations
|
|
776
|
R2 / Ω02
|
|
.235 / .233
|
sjPlot::sjt.lmer(lme4::lmer(final_grade ~ pre_uv + pre_int + pre_percomp + gender + I(time_spent/60) + (1 | course_ID), data = d))
|
|
final_grade
|
|
|
B
|
CI
|
p
|
Fixed Parts
|
(Intercept)
|
|
50.54
|
39.38 – 61.69
|
<.001
|
pre_uv
|
|
-3.27
|
-5.87 – -0.67
|
.014
|
pre_int
|
|
4.64
|
1.52 – 7.75
|
.004
|
pre_percomp
|
|
2.34
|
-0.25 – 4.94
|
.077
|
gender (M)
|
|
-4.98
|
-8.06 – -1.91
|
.002
|
I(time_spent/60)
|
|
0.36
|
0.30 – 0.42
|
<.001
|
Random Parts
|
σ2
|
|
348.602
|
τ00, course_ID
|
|
34.424
|
Ncourse_ID
|
|
36
|
ICCcourse_ID
|
|
0.090
|
Observations
|
|
750
|
R2 / Ω02
|
|
.248 / .246
|
7B. SEM (but no accounting for nesting)
indirect effect of UV
library(lavaan)
d$ts_60 <- d$time_spent / 60
d$male_dummy <- ifelse(d$gender == "M", 1, 0)
m1 <- '
# regressions
ts_60 ~ pre_uv + pre_int + pre_percomp + male_dummy
final_grade ~ ts_60 + pre_uv + pre_int + pre_percomp
'
out1 <- sem(m1, data = d)
summary(out1)
## lavaan (0.5-23.1097) converged normally after 76 iterations
##
## Used Total
## Number of observations 750 809
##
## Estimator ML
## Minimum Function Test Statistic 4.889
## Degrees of freedom 1
## P-value (Chi-square) 0.027
##
## Parameter Estimates:
##
## Information Expected
## Standard Errors Standard
##
## Regressions:
## Estimate Std.Err z-value P(>|z|)
## ts_60 ~
## pre_uv 3.617 1.444 2.505 0.012
## pre_int 0.108 1.760 0.061 0.951
## pre_percomp -0.121 1.563 -0.077 0.939
## male_dummy -4.754 1.833 -2.593 0.010
## final_grade ~
## ts_60 0.317 0.032 10.013 0.000
## pre_uv -4.052 1.264 -3.206 0.001
## pre_int 5.335 1.509 3.535 0.000
## pre_percomp 1.955 1.361 1.436 0.151
##
## Variances:
## Estimate Std.Err z-value P(>|z|)
## .ts_60 506.077 26.134 19.365 0.000
## .final_grade 384.902 19.876 19.365 0.000
m2 <- '
# regressions
ts_60 ~ a*pre_uv + pre_int + pre_percomp + male_dummy
final_grade ~ b*ts_60 + c*pre_uv + pre_int + pre_percomp
# indirect effect (a*b)
ab := a*b
# total effect
total := c + (a*b)
'
out2 <- sem(m2, data = d)
summary(out2)
## lavaan (0.5-23.1097) converged normally after 76 iterations
##
## Used Total
## Number of observations 750 809
##
## Estimator ML
## Minimum Function Test Statistic 4.889
## Degrees of freedom 1
## P-value (Chi-square) 0.027
##
## Parameter Estimates:
##
## Information Expected
## Standard Errors Standard
##
## Regressions:
## Estimate Std.Err z-value P(>|z|)
## ts_60 ~
## pre_uv (a) 3.617 1.444 2.505 0.012
## pre_int 0.108 1.760 0.061 0.951
## pre_percmp -0.121 1.563 -0.077 0.939
## male_dummy -4.754 1.833 -2.593 0.010
## final_grade ~
## ts_60 (b) 0.317 0.032 10.013 0.000
## pre_uv (c) -4.052 1.264 -3.206 0.001
## pre_int 5.335 1.509 3.535 0.000
## pre_percmp 1.955 1.361 1.436 0.151
##
## Variances:
## Estimate Std.Err z-value P(>|z|)
## .ts_60 506.077 26.134 19.365 0.000
## .final_grade 384.902 19.876 19.365 0.000
##
## Defined Parameters:
## Estimate Std.Err z-value P(>|z|)
## ab 1.148 0.473 2.430 0.015
## total -2.904 1.340 -2.167 0.030
7C. Let’s run the same two models accounting for clustering
library(survey)
library(lavaan.survey)
group <- svydesign(ids= ~course_ID, data = d)
out1_c <- lavaan.survey(out1, group)
summary(out1_c)
## lavaan (0.5-23.1097) converged normally after 77 iterations
##
## Number of observations 750
##
## Estimator ML Robust
## Minimum Function Test Statistic 4.889 0.111
## Degrees of freedom 1 1
## P-value (Chi-square) 0.027 0.739
## Scaling correction factor 44.063
## for the Satorra-Bentler correction
##
## Parameter Estimates:
##
## Information Expected
## Standard Errors Robust.sem
##
## Regressions:
## Estimate Std.Err z-value P(>|z|)
## ts_60 ~
## pre_uv 3.617 1.848 1.958 0.050
## pre_int 0.108 2.033 0.053 0.958
## pre_percomp -0.121 2.282 -0.053 0.958
## male_dummy -4.754 2.375 -2.001 0.045
## final_grade ~
## ts_60 0.317 0.029 10.890 0.000
## pre_uv -4.052 1.525 -2.657 0.008
## pre_int 5.335 2.505 2.129 0.033
## pre_percomp 1.955 1.817 1.076 0.282
##
## Intercepts:
## Estimate Std.Err z-value P(>|z|)
## .ts_60 19.690 5.809 3.390 0.001
## .final_grade 52.606 8.219 6.401 0.000
##
## Variances:
## Estimate Std.Err z-value P(>|z|)
## .ts_60 506.028 72.959 6.936 0.000
## .final_grade 384.864 28.598 13.458 0.000
out2_c <- lavaan.survey(out2, group)
summary(out2_c)
## lavaan (0.5-23.1097) converged normally after 77 iterations
##
## Number of observations 750
##
## Estimator ML Robust
## Minimum Function Test Statistic 4.889 0.111
## Degrees of freedom 1 1
## P-value (Chi-square) 0.027 0.739
## Scaling correction factor 44.063
## for the Satorra-Bentler correction
##
## Parameter Estimates:
##
## Information Expected
## Standard Errors Robust.sem
##
## Regressions:
## Estimate Std.Err z-value P(>|z|)
## ts_60 ~
## pre_uv (a) 3.617 1.848 1.958 0.050
## pre_int 0.108 2.033 0.053 0.958
## pre_percmp -0.121 2.282 -0.053 0.958
## male_dummy -4.754 2.375 -2.001 0.045
## final_grade ~
## ts_60 (b) 0.317 0.029 10.890 0.000
## pre_uv (c) -4.052 1.525 -2.657 0.008
## pre_int 5.335 2.505 2.129 0.033
## pre_percmp 1.955 1.817 1.076 0.282
##
## Intercepts:
## Estimate Std.Err z-value P(>|z|)
## .ts_60 19.690 5.809 3.390 0.001
## .final_grade 52.606 8.219 6.401 0.000
##
## Variances:
## Estimate Std.Err z-value P(>|z|)
## .ts_60 506.028 72.959 6.936 0.000
## .final_grade 384.864 28.598 13.458 0.000
##
## Defined Parameters:
## Estimate Std.Err z-value P(>|z|)
## ab 1.148 0.609 1.886 0.059
## total -2.904 1.409 -2.061 0.039