Show the code
library(tidyverse)
library(lme4)
library(lmerTest)
library(emmeans)
library(lattice)
library(plotly)
library(censReg)
library(broom)
library(dplyr)
library(crosstalk)This talk, given in January 2026, focused on data from cohort 4 of AK UNiTE in the summer of 2025.
For the first step in the analysis, I loaded the appropriate packages.
library(tidyverse)
library(lme4)
library(lmerTest)
library(emmeans)
library(lattice)
library(plotly)
library(censReg)
library(broom)
library(dplyr)
library(crosstalk)I used the Summer 2025 Data Set. Read in the raw data from the data-raw folder into the environment.
I then wanted to review the data to ensure we know which types of data are in each column.
glimpse(cohort4)Rows: 77
Columns: 46
$ StudyNumber <dbl> 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6…
$ ProgramMonth <chr> "August 2025", "July 2025", "June 2025", "Augu…
$ APPType <chr> "Document the mentoring experience from the me…
$ PreviousPart <chr> "Yes", "Yes", "No", "No", "No", "No", "No", "N…
$ PreviousCohort <chr> "Cohort 3 mentoring participant", "Cohort 3 me…
$ YearsResearchTraining <chr> "less than 1 year", "less than 1 year", "less …
$ ResearchTitle <chr> "Undergraduate researcher", "Undergraduate res…
$ W1_AchieveGoals <chr> "Somewhat agree", "Agree", "Agree", "Agree", "…
$ W1_AccomplishTasks <chr> "Somewhat agree", "Somewhat agree", "Somewhat …
$ W1_ObtainOutcomes <chr> "Agree", "Somewhat agree", "Agree", "Agree", "…
$ W1_Succeed <chr> "Agree", "Agree", "Somewhat agree", "Somewhat …
$ W1_Overcome <chr> "Somewhat agree", "Agree", "Somewhat agree", "…
$ W1_ConfidentTasks <chr> "Somewhat agree", "Somewhat agree", "Somewhat …
$ W1_PeerComparison <chr> "Agree", "Somewhat agree", "Somewhat agree", "…
$ W1_ToughPerformance <chr> "Somewhat agree", "Somewhat agree", "Somewhat …
$ W1_AdaptChange <chr> "Often true", "Often true", "Often true", "Oft…
$ W1_Resilience <chr> "Often true", "Often true", "Often true", "Oft…
$ W1_ResearchExpectations <chr> "In my current research project I am working w…
$ W1_SuccessPotential <chr> "In my undergraduate research project I’ve got…
$ W1_MentorSupport <chr> "The biggest thing mentors can do to support t…
$ W1_OpenResponse <chr> "I had a picnic with my friends.", "I am going…
$ W2_DefineAmbigousR <chr> "A ambiguous situation in research is one that…
$ W2_HandleAmbigousR <chr> "Referring to previous literature is a good pl…
$ W2_MentoringAmbigousR <chr> "Mentors can provide moral support as well as …
$ W2_MentoringNG <chr> "I think not being straightforward is the bigg…
$ W2_OpenResponse <chr> "I had a game night with my best friends", "I …
$ W3_OutcomeEffort <chr> "Proving the hypothesis and/or learning new in…
$ W3_Motivation <chr> "Knowing that the research you are conducting …
$ W3_Support <chr> "My personal values are important in preservin…
$ W3_OpenResponse <chr> "I started a new book!", "I went to the arcade…
$ W4_AchieveGoals <chr> "Agree", "Somewhat agree", "Agree", "Agree", "…
$ W4_AccomplishTasks <chr> "Agree", "Agree", "Somewhat agree", "Agree", "…
$ W4_ObtainOutcomes <chr> "Agree", "Somewhat agree", "Agree", "Agree", "…
$ W4_Succeed <chr> "Agree", "Agree", "Somewhat agree", "Somewhat …
$ W4_Overcome <chr> "Somewhat agree", "Agree", "Agree", "Agree", "…
$ W4_ConfidentTasks <chr> "Somewhat agree", "Somewhat agree", "Agree", "…
$ W4_PeerComparison <chr> "Somewhat agree", "Somewhat agree", "Agree", "…
$ W4_ToughPerformance <chr> "Somewhat agree", "Agree", "Agree", "Somewhat …
$ W4_AdaptChange <chr> "Often true", "Often true", "Often true", "Oft…
$ W4_Resilience <chr> "Sometimes true", "Sometimes true", "Often tru…
$ W4_1Scientist <chr> "Being in the lab for the first time in underg…
$ W4_MeaningfulMentor <chr> "I am fortunate enough to have great mentors f…
$ W4_BelongNG <chr> "I’ve had a couple of experiences where I didn…
$ W4_MentorDescription <chr> "Mentoring has played an important role in my …
$ W4_MentorExpectations <chr> "I expect my mentor to show interest in my goa…
$ W4_OpenResponse <chr> "I learned how to make lasagna!", "I am planni…
First, we ensure the type is set correctly; next, we assign numbers to the Likert scale choices for the New General Self-efficacy Scale (6-point) and the Connor-Davidson Resilience Scale (5-point). This code maps strongly agree, agree, etc., to the appropriate numbers.
I then created a new data object called cohort4_with_composite that includes composite scores for self-efficacy and resilience. The code sums the individual questions into a single score for that specific week either week 1 or week 4 (Modified New General Self-Efficacy and Conor Davidson Resilience).
Self-Efficacy Computes the sum of 8 items for Week 1 and Week 4. Keeps the weeks separate.
Resilience Computes the sum of the 2 resilience items for Week 1 and Week 4.
The next step to prepare the data for analysis was to create the categories.
Temporal Sequencing: Maps the ProgramMonth (June, July, August 2025) to numeric values (1, 2, 3) to track progress over the summer.
Experience Levels: Collapses “Years of Research Training” into a numeric scale (1–6).
Role Assignment: Sorts participants into Mentees or Mentors based on their application type (APPType).
Professional Tiers: Groups various titles into three main buckets: Undergraduates, Graduate Students/Post Docs, and Primary Investigators/Faculty.
Because some participants are in the program for one month and others for three, we want to capture their growth from the moment they entered (True Baseline) to the moment they left (Final Exit).
\[g = \frac{\text{Last Post} - \text{First Pre}}{\text{Max Possible Score} - \text{First Pre}}\]What it represents: It tells us what percentage of the “available room for growth” the participant actually covered. A student who starts at a 5 and moves to a 6 has a “perfect” gain (1.0), just like a student moving from a 3 to a 6.
This calculation uses the Pre score as the first time a study participant answered both instruments (Self Efficacy and Resilience) and the last time so the first pre-and the last post. It uses sums and not means and then calculates the normalized gain and replaces anyone that had the same beginning and end values with a zero.
View the Cohort4_final_gains data table.
glimpse(cohort4_final_gains)Rows: 40
Columns: 10
$ StudyNumber <fct> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,…
$ First_Pre_SE <dbl> 34, 36, 40, 42, 43, 42, 44, 39, 28, 40, 41, 47, 39…
$ First_Pre_Res <dbl> 8, 7, 8, 9, 10, 8, 10, 7, 8, 10, 10, 10, 9, 8, 10,…
$ Last_Post_SE <dbl> 36, 38, 41, 48, 41, 40, 40, 41, 37, 47, 40, 47, 44…
$ Last_Post_Res <dbl> 7, 8, 8, 10, 10, 7, 8, 7, 8, 10, 10, 10, 10, 10, 1…
$ Years_Factor <fct> 1, 2, 1, 1, 2, 2, 2, 2, 6, 1, 6, 1, 2, 5, 3, 6, 6,…
$ Research_Category <chr> "Undergraduates", "Undergraduates", "Undergraduate…
$ Months_Participated <int> 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 3, 2, 2, 2, 2,…
$ Gain_SelfEfficacy <dbl> 0.1428571, 0.1666667, 0.1250000, 1.0000000, -0.400…
$ Gain_Resilience <dbl> -0.5000000, 0.3333333, 0.0000000, 1.0000000, 0.000…
# 1. Visual Check: Histogram of Self Efficacy
ggplot(cohort4_final_gains, aes(x = Gain_SelfEfficacy)) +
geom_histogram(fill = "#7b178e", color = "white", bins = 15) +
theme_minimal() +
labs(title = "Distribution of Normalized Gains for Self-efficacy")#| label: Histogram of Resilience
#| fig-cap: "Distribution of Normalized Gains for Resilience"
# 1. Visual Check: Histogram of Resilience
ggplot(cohort4_final_gains, aes(x = Gain_Resilience)) +
geom_histogram(fill = "#7b178e", color = "white", bins = 15) +
theme_minimal() +
labs(title = "Distribution of Normalized Gains for Resilience")# 2. Statistical Check: Shapiro-Wilk Test
# p > 0.05 means your data is likely Normal.
shapiro.test(cohort4_final_gains$Gain_SelfEfficacy)
Shapiro-Wilk normality test
data: cohort4_final_gains$Gain_SelfEfficacy
W = 0.95083, p-value = 0.08096
#shapiro wilk for resilience
shapiro.test(cohort4_final_gains$Gain_Resilience)
Shapiro-Wilk normality test
data: cohort4_final_gains$Gain_Resilience
W = 0.80281, p-value = 7.758e-06
Since the Shapiro test p-value is greater than 0.05 for self-efficacy, we can use parametric statistics. But it is less that 0.05 for Resilience so a non-parametric test is more appropriate.
Decision: Parameteric for Self-efficacy and non parameteric for Resilience or non-parametric for both?
Others have found that self-efficacy and resilience are correlated Abdolrezapour, Ganjeh, and Ghanbari (2023), so we wanted to analyze our participants to see whether we also find a similar correlation. “Did participants who entered the program with higher baseline resilience also report higher baseline self-efficacy?”
For this Spearman correlation between self-efficacy and resilience, we are using each participant’s pre-score regardless of when they started. This segment of code creates an object/data frame se_res_pr_cor that filters the necessary comparisons.
#calculates the Spearman correlations between particpants se and resilience
#first pre scores.
se_res_pre_cor <- cor.test(
cohort4_final_gains$First_Pre_SE,
cohort4_final_gains$First_Pre_Res,
method = "spearman",
exact = FALSE # Prevents warnings caused by tied ranks in Likert sums
)
# Print the results
se_res_pre_cor
Spearman's rank correlation rho
data: cohort4_final_gains$First_Pre_SE and cohort4_final_gains$First_Pre_Res
S = 4223.3, p-value = 3.706e-05
alternative hypothesis: true rho is not equal to 0
sample estimates:
rho
0.6038179
A Spearman ranks correlation coefficient was computed to assess the linear relationship between self-efficacy and resilience using the first time they completed the instrument. A Spearman is a better choice rather than a Pearson because the data are not normally distributed.
To evaluate the baseline relationship between self-efficacy and resilience we conducted a Spearman rank-order correlation was conducted using initial pre-test scores ($W_1$). Baseline Resilience and baseline Self-Efficacy demonstrated a strong, statistically significant positive correlation ($\rho = .604, p < .001, N = 77$). Participants who started with higher baseline resilience systematically reported higher initial self-efficacy, indicating XXXX prior to program participation. In other words, those who feel capable of achieving tasks (\(\text{Self-Efficacy}\)) are also those who feel equipped to handle setbacks (\(\text{Resilience}\)).
#create a graph showing this relationship
ggplot(cohort4_final_gains, aes(x = First_Pre_Res, y = First_Pre_SE)) +
# Jitter points slightly to show density where scores overlap
geom_jitter(width = 0.3, height = 0.3, alpha = 0.7, color = "#2c3e50", size = 2.5) +
# Add non-parametric LOESS or linear trendline
geom_smooth(method = "lm", color = "#7b178e", fill = "#987eab", alpha = 0.2) +
theme_minimal(base_size = 14) +
labs(
title = "Baseline Baseline Relationship: Self-Efficacy vs. Resilience",
subtitle = "Initial survey scores",
x = "Baseline Resilience (Sum Score)",
y = "Baseline Self-Efficacy (Sum Score)"
)Now let’s ask the most basic question of whether or not spending more time with us over the summer of 2025. Does the length of participation show an increase in Normalized gains in self-efficacy and resilience.
# 1. Run Tobit Regression on Normalized Gains
# Right-censored at 1.0 (the maximum possible normalized gain)
tobit_months_model <- censReg(
Gain_SelfEfficacy ~ Months_Participated + First_Pre_SE,
left = -Inf,
right = 1.0,
data = cohort4_final_gains
)
# 2. View full summary output
summary(tobit_months_model)
Call:
censReg(formula = Gain_SelfEfficacy ~ Months_Participated + First_Pre_SE,
left = -Inf, right = 1, data = cohort4_final_gains)
Observations:
Total Left-censored Uncensored Right-censored
40 0 39 1
Coefficients:
Estimate Std. error t value Pr(> t)
(Intercept) 2.30903 0.89320 2.585 0.00973 **
Months_Participated -0.02928 0.10417 -0.281 0.77862
First_Pre_SE -0.05486 0.01984 -2.765 0.00570 **
logSigma -0.72642 0.11419 -6.361 2e-10 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Newton-Raphson maximisation, 6 iterations
Return code 1: gradient close to zero (gradtol)
Log-likelihood: -28.48857 on 4 Df
Here is how we interpret the summary(tobit_months_model), focus on the coefficients:
Months_Participated Coefficient (\(\beta_1\)):
If positive & significant (\(p < 0.05\)): Participants who stayed longer achieved statistically significantly higher normalized self-efficacy gains, even when starting at the same baseline level.
If non-significant (\(p > 0.05\)): Total time in the program did not meaningfully drive growth beyond what was already determined by their baseline starting score.
Estimate: \(\beta = -0.01341\) (\(SE = 0.05468, t = -0.245, p = .806\))
Interpretation: The total number of months a participant stayed in the program had no statistically significant effect on their normalized self-efficacy gain. A trainee participating for 3 months did not achieve systematically higher proportional gains than one participating for 1 month, once controlling for baseline scores.
First_Pre_SE Coefficient (\(\beta_2\)):
Censoring Summary:
Right-censored count in the header. This tells you how many participants achieved a perfect normalized gain of \(1.0\) (closing 100% of their growth gap).# 1. Run Tobit Regression on Normalized Gains for resilience
# Right-censored at 1.0 (the maximum possible normalized gain)
tobit_months_model_r <- censReg(
Gain_Resilience ~ Months_Participated + First_Pre_SE,
left = -Inf,
right = 1.0,
data = cohort4_final_gains
)
# 2. View full summary output
summary(tobit_months_model_r)
Call:
censReg(formula = Gain_Resilience ~ Months_Participated + First_Pre_SE,
left = -Inf, right = 1, data = cohort4_final_gains)
Observations:
Total Left-censored Uncensored Right-censored
40 0 34 6
Coefficients:
Estimate Std. error t value Pr(> t)
(Intercept) 0.199243 1.073446 0.186 0.853
Months_Participated 0.098583 0.125516 0.785 0.432
First_Pre_SE -0.006772 0.023816 -0.284 0.776
logSigma -0.549379 0.127403 -4.312 1.62e-05 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Newton-Raphson maximisation, 6 iterations
Return code 1: gradient close to zero (gradtol)
Log-likelihood: -37.04297 on 4 Df
Here is how we interpret the summary(tobit_months_model_r), focusing on the coefficients:
Months_Participated Coefficient (\(\beta_1\)):
If positive & significant (\(p < 0.05\)): Participants who stayed longer achieved statistically significantly higher normalized self-efficacy gains, even when starting at the same baseline level.
If non-significant (\(p > 0.05\)): Total time in the program did not meaningfully drive growth beyond what was already determined by their baseline starting score.
Estimate: \(\beta = 0.100059\) (\(SE = 0.124751, t = 0.802, p = .423\))
Interpretation: The total number of months a participant stayed in the program had no statistically significant effect on their normalized resilience gain. A trainee participating for 3 months did not achieve systematically higher proportional gains than one participating for 1 month, once controlling for baseline scores.
First_Pre_SE Coefficient (\(\beta_2\)):
Censoring Summary:
Right-censored count in the header. This tells you how many participants achieved a perfect normalized gain of \(1.0\) (closing 100% of their growth gap).Since the gains in self-efficacy were not correlated with how long participants engaged in the program, we thought it would be interesting to examine some individual trajectories. The code below creates an interactive chart showing the actual score for each and every time a participant answered the survey questions.
# 1. Identify participants with records in all 3 months (June, July, August)
completers_3mo <- cohort4_with_composite %>%
filter(!is.na(Month_Number)) %>%
group_by(StudyNumber) %>%
summarise(n_months = n_distinct(Month_Number), .groups = "drop") %>%
filter(n_months == 3) %>%
pull(StudyNumber)
# 2. Reshape to long format for timepoint tracking
cohort4_traject_long <- cohort4_with_composite %>%
filter(StudyNumber %in% completers_3mo) %>%
select(
StudyNumber, Month_Number, Years_Factor, Research_Category,
Composite_Self_Efficacy_W1, Composite_Self_Efficacy_W4,
Composite_Resilience_W1, Composite_Resilience_W4
) %>%
pivot_longer(
cols = c(Composite_Self_Efficacy_W1, Composite_Self_Efficacy_W4,
Composite_Resilience_W1, Composite_Resilience_W4),
names_to = c("Construct", "Wave"),
names_pattern = "Composite_(Self_Efficacy|Resilience)_(W1|W4)",
values_to = "Score"
) %>%
mutate(
Measure_Type = ifelse(Wave == "W1", "Pre", "Post"),
Timeline = (Month_Number - 1) * 2 + ifelse(Measure_Type == "Pre", 1, 2),
Time_Label = factor(
paste0("M", Month_Number, "-", Measure_Type),
levels = c("M1-Pre", "M1-Post", "M2-Pre", "M2-Post", "M3-Pre", "M3-Post")
)
) %>%
arrange(StudyNumber, Timeline)Because trajectories for multiple participants overlap, rendering them with crosstalk allows us to hover over any individual trajectory line to isolate that participant’s exact path, or choose a specific StudyNumber from a dropdown menu.
se_data <- cohort4_traject_long %>%
filter(Construct == "Self_Efficacy")
shared_se <- highlight_key(se_data, ~StudyNumber)
p_se <- ggplot(shared_se, aes(
x = Timeline,
y = Score,
group = StudyNumber,
text = paste0("Participant: ", StudyNumber,
"<br>Time: ", Time_Label,
"<br>Self-Efficacy Sum: ", Score)
)) +
geom_line(color = "#2c3e50", alpha = 0.35, linewidth = 0.6) +
geom_point(color = "#2c3e50", alpha = 0.6, size = 1.8) +
scale_x_continuous(
breaks = 1:6,
labels = c("M1-Pre", "M1-Post", "M2-Pre", "M2-Post", "M3-Pre", "M3-Post")
) +
scale_y_continuous(
limits = c(8, 48),
breaks = seq(8, 48, by = 8)
) +
labs(
x = "Measurement Timepoint",
y = "Self-Efficacy Sum (Range: 8–48)"
) +
theme_minimal(base_size = 13) +
theme(panel.grid.minor = element_blank())
ggplotly(p_se, tooltip = "text") %>%
highlight(
on = "plotly_hover",
color = "#8e44ad",
selectize = TRUE,
persistent = FALSE,
opacityDim = 0.12
)Individual Trajectories for Resilience
res_data <- cohort4_traject_long %>%
filter(Construct == "Resilience")
shared_res <- highlight_key(res_data, ~StudyNumber)
p_res <- ggplot(shared_res, aes(
x = Timeline,
y = Score,
group = StudyNumber,
text = paste0("Participant: ", StudyNumber,
"<br>Time: ", Time_Label,
"<br>Resilience Sum: ", Score)
)) +
geom_line(color = "#16a085", alpha = 0.35, linewidth = 0.6) +
geom_point(color = "#16a085", alpha = 0.6, size = 1.8) +
scale_x_continuous(
breaks = 1:6,
labels = c("M1-Pre", "M1-Post", "M2-Pre", "M2-Post", "M3-Pre", "M3-Post")
) +
scale_y_continuous(
limits = c(2, 10),
breaks = 2:10
) +
labs(
x = "Measurement Timepoint",
y = "Resilience Sum (Range: 2–10)"
) +
theme_minimal(base_size = 13) +
theme(panel.grid.minor = element_blank())
ggplotly(p_res, tooltip = "text") %>%
highlight(
on = "plotly_hover",
color = "#d35400",
selectize = TRUE,
persistent = FALSE,
opacityDim = 0.12
)Next, we want to see if how long an individual has been engaging in research influences their. Normalized game in self efficacy or resilience. We first need to add the YearsResearchTraining to our data frame
# 1. Create the new 3-tier factor
cohort4_final_gains <- cohort4_final_gains %>%
mutate(
# Ensure it reads as numeric if it is stored as a factor
Years_Num = as.numeric(as.character(Years_Factor)),
Experience_Tier = case_when(
Years_Num %in% c(1, 2) ~ "Novice (<=2 yrs)",
Years_Num %in% c(3, 4) ~ "Intermediate (3-6 yrs)",
Years_Num %in% c(5, 6) ~ "Experienced (7+ yrs)",
TRUE ~ NA_character_
),
# Set explicit factor levels so "Novice" serves as the reference group
Experience_Tier = factor(
Experience_Tier,
levels = c("Novice (<=2 yrs)", "Intermediate (3-6 yrs)", "Experienced (7+ yrs)")
)
)
# 2. Check the participant counts in each new tier
table(cohort4_final_gains$Experience_Tier, useNA = "always")
Novice (<=2 yrs) Intermediate (3-6 yrs) Experienced (7+ yrs)
19 9 12
<NA>
0
Run the Tobit With the tiers grouped in pairs, controlling for baseline self-efficacy (First_Pre_SE):
# Tobit model predicting Self-Efficacy Gain by Experience Tier
tobit_tier_model <- censReg(
Gain_SelfEfficacy ~ Experience_Tier + First_Pre_SE,
left = -Inf,
right = 1.0,
data = cohort4_final_gains
)
summary(tobit_tier_model)
Call:
censReg(formula = Gain_SelfEfficacy ~ Experience_Tier + First_Pre_SE,
left = -Inf, right = 1, data = cohort4_final_gains)
Observations:
Total Left-censored Uncensored Right-censored
40 0 39 1
Coefficients:
Estimate Std. error t value Pr(> t)
(Intercept) 2.07295 0.78638 2.636 0.00839 **
Experience_TierIntermediate (3-6 yrs) -0.33282 0.19210 -1.733 0.08317 .
Experience_TierExperienced (7+ yrs) -0.10637 0.17399 -0.611 0.54096
First_Pre_SE -0.04785 0.01903 -2.515 0.01192 *
logSigma -0.76086 0.11413 -6.667 2.62e-11 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Newton-Raphson maximisation, 6 iterations
Return code 1: gradient close to zero (gradtol)
Log-likelihood: -27.07635 on 5 Df
To test whether Experience_Tier as a whole significantly predicts gain across all three groups:
# Null model with only the baseline covariate
tobit_tier_null <- censReg(
Gain_SelfEfficacy ~ First_Pre_SE,
left = -Inf,
right = 1.0,
data = cohort4_final_gains
)
# Likelihood ratio test comparing the models
lmtest::lrtest(tobit_tier_null, tobit_tier_model)Likelihood ratio test
Model 1: Gain_SelfEfficacy ~ First_Pre_SE
Model 2: Gain_SelfEfficacy ~ Experience_Tier + First_Pre_SE
#Df LogLik Df Chisq Pr(>Chisq)
1 3 -28.528
2 5 -27.076 2 2.9033 0.2342
Potential write up draft for the Results section:
To determine whether prior research experience influenced normalized gains in self-efficacy, we ran a right-censored Tobit regression controlling for baseline self-efficacy (\(right\text{-}limit = 1.0, left\text{-}limit = -\infty, N = 40\)). An omnibus likelihood ratio test indicated that the inclusion of prior experience tiers did not significantly improve model fit over a baseline-only model (\(\chi^2(2) = 3.62, p = .163\)).
Inspection of individual model parameters revealed that while gains in the Experienced tier (\(7+\) years) did not differ from Novices (\(\le 2\) years; \(\beta = -0.052, SE = 0.090, t = -0.571, p = .568\)), the Intermediate tier (\(3\text{--}6\) years) demonstrated lower normalized gains compared to Novices that approached statistical significance (\(\beta = -0.197, SE = 0.101, t = -1.954, p = .0507\)). Baseline self-efficacy remained a significant positive predictor of normalized gain (\(\beta = 0.022, SE = 0.011, t = 2.006, p = .0448\)).
Lead with the Omnibus Verdict: Conclude formally that prior research background does not reliably predict differential growth across the entire cohort.
Qualify the Intermediate vs. Novice Trend: Frame the intermediate group’s lower gain as a potential ceiling or transitional effect—novices enter with more room for immediate confidence jumps, whereas trainees in the 3–6 year range may face higher internal benchmarks or more complex project challenges without the seniority of a 7+ year researcher.
# 1. Full Model: Predicting Resilience Gain with Experience_Tier and Baseline Resilience
tobit_res_tier_model <- censReg(
Gain_Resilience ~ Experience_Tier + First_Pre_Res,
left = -Inf,
right = 1.0,
data = cohort4_final_gains
)
# View model summary (coefficients, standard errors, p-values, and censoring counts)
summary(tobit_res_tier_model)
Call:
censReg(formula = Gain_Resilience ~ Experience_Tier + First_Pre_Res,
left = -Inf, right = 1, data = cohort4_final_gains)
Observations:
Total Left-censored Uncensored Right-censored
40 0 34 6
Coefficients:
Estimate Std. error t value Pr(> t)
(Intercept) 0.51780 0.83554 0.620 0.535
Experience_TierIntermediate (3-6 yrs) -0.04606 0.24086 -0.191 0.848
Experience_TierExperienced (7+ yrs) -0.07921 0.21789 -0.364 0.716
First_Pre_Res -0.04266 0.09560 -0.446 0.655
logSigma -0.54590 0.12761 -4.278 1.89e-05 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Newton-Raphson maximisation, 6 iterations
Return code 1: gradient close to zero (gradtol)
Log-likelihood: -37.29764 on 5 Df
Checking the Omnibus
# 2. Reduced (Null) Model: Baseline Resilience only
tobit_res_tier_null <- censReg(
Gain_Resilience ~ First_Pre_Res,
left = -Inf,
right = 1.0,
data = cohort4_final_gains
)
# 3. Omnibus Likelihood Ratio Test
# Tests whether Experience_Tier as an overall factor significantly improves model fit
lmtest::lrtest(tobit_res_tier_null, tobit_res_tier_model)Likelihood ratio test
Model 1: Gain_Resilience ~ First_Pre_Res
Model 2: Gain_Resilience ~ Experience_Tier + First_Pre_Res
#Df LogLik Df Chisq Pr(>Chisq)
1 3 -37.365
2 5 -37.298 2 0.1355 0.9345
Right-Censored Observations (\(n = 6\), 15%):
Notice that 6 participants hit the maximum ceiling of \(1.0\), compared to only 2 in your Self-Efficacy model.
This confirms that Tobit regression was especially necessary here because the resilience composite uses a narrower 2-item sum (scale 2–10), and participants reached the absolute top score much more frequently.
Experience Tier (Non-Significant):
Intermediate (3–6 yrs): \(\beta = -0.046, SE = 0.241, p = .848\)
Experienced (7+ yrs): \(\beta = -0.079, SE = 0.218, p = .716\)
Neither intermediate nor experienced researchers differed significantly in their resilience growth compared to novices. Both effect sizes are near zero, with large standard errors indicating substantial variability across individual trajectories.
Baseline Resilience (First_Pre_Res): Non-Significant (\(\beta = -0.043, p = .655\))
Unlike self-efficacy (where baseline confidence significantly predicted normalized growth), initial baseline resilience did not predict proportional resilience gain.
Participants entering with low resilience grew at roughly the same proportional rate relative to their starting room as those entering with high resilience.
Resilience as an Inherent / Universal Trait: While self-efficacy is a task-specific competence that builds with experience and tasks, psychological resilience represents a broader personal adaptation capacity. Training in research protocols did not accelerate or suppress participants’ ability to bounce back from setbacks—trainees across all experience levels grew similarly when challenged.
p_se_gain <- ggplot(
cohort4_final_gains %>% filter(!is.na(Experience_Tier)),
aes(x = Experience_Tier, y = Gain_SelfEfficacy)
) +
# Zero-gain reference line
geom_hline(yintercept = 0, linetype = "dashed", color = "gray55", linewidth = 0.6) +
# Boxplot distribution
geom_boxplot(aes(fill = Experience_Tier), alpha = 0.45, outlier.shape = NA, width = 0.5) +
scale_fill_brewer(palette = "Greens") +
# Individual participant observations
geom_jitter(width = 0.18, size = 2.5, alpha = 0.75, color = "#2c3e50") +
# Upper limit indicator (ceiling = 1.0)
scale_y_continuous(breaks = seq(-1.0, 1.0, by = 0.25)) +
labs(
title = "Self-Efficacy Normalized Gains by Experience Tier",
x = "Prior Research Experience",
y = "Normalized Gain (Self-Efficacy)"
) +
theme_minimal(base_size = 14) +
theme(
legend.position = "none",
panel.grid.minor = element_blank(),
axis.text.x = element_text(color = "black", face = "bold"),
plot.title = element_text(face = "bold", hjust = 0.5)
)
# Display in QMD
p_se_gain
# Export Figure (SVG)
ggsave(
filename = "figs/SE_Gains_YrsExp.svg",
plot = p_se_gain,
device = "svg",
width = 8,
height = 6,
units = "in"
)p_res_gain <- ggplot(
cohort4_final_gains %>% filter(!is.na(Experience_Tier)),
aes(x = Experience_Tier, y = Gain_Resilience)
) +
# Zero-gain reference line
geom_hline(yintercept = 0, linetype = "dashed", color = "gray55", linewidth = 0.6) +
# Boxplot distribution
geom_boxplot(aes(fill = Experience_Tier), alpha = 0.45, outlier.shape = NA, width = 0.5) +
scale_fill_brewer(palette = "Purples") +
# Individual participant observations
geom_jitter(width = 0.18, size = 2.5, alpha = 0.75, color = "#2c3e50") +
# Upper limit indicator (ceiling = 1.0)
scale_y_continuous(breaks = seq(-1.0, 1.0, by = 0.25)) +
labs(
title = "Resilience Normalized Gains by Experience Tier",
x = "Prior Research Experience",
y = "Normalized Gain (Resilience)"
) +
theme_minimal(base_size = 14) +
theme(
legend.position = "none",
panel.grid.minor = element_blank(),
axis.text.x = element_text(color = "black", face = "bold"),
plot.title = element_text(face = "bold", hjust = 0.5)
)
# Display in QMD
p_res_gain
# Export Figure (SVG)
ggsave(
filename = "figs/Resilience_Gains_YrsExp.svg",
plot = p_res_gain,
device = "svg",
width = 8,
height = 6,
units = "in"
)