Math Anxiety Spring 2025 Project

Load Libraries

library(ggplot2)
library(dplyr)

Attaching package: 'dplyr'
The following objects are masked from 'package:stats':

    filter, lag
The following objects are masked from 'package:base':

    intersect, setdiff, setequal, union
library(tidyr)
library(tidyverse)
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ forcats   1.0.0     ✔ readr     2.1.5
✔ lubridate 1.9.4     ✔ stringr   1.5.1
✔ purrr     1.0.4     ✔ tibble    3.2.1
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(psych)

Attaching package: 'psych'

The following objects are masked from 'package:ggplot2':

    %+%, alpha
library(readr)
library(skimr)
library(ggpubr) # for ggplot statline and equation

Import Datasets

# Week 1 Survey - Contains Math Anxiety (Trait) and Background Questions
df1 <- read.csv("/cloud/project/data/sp25-w1-survey.csv")

# Week 3 Survey - Contains Math Anxiety (State) Questions
df3 <- read.csv("/cloud/project/data/sp25-w3-survey.csv")

# Week 3 Math Scores - Contains Students' Math Assessment Scores
dfscores <- read.csv("/cloud/project/data/sp25-w3-mathscores.csv")

# Week 8 Survey - Contains AI Tutor Math Anxiety and Perception Questions
df8 <- read.csv("/cloud/project/data/sp25-w8-survey.csv")

Merging Dataframes

dfm1 <- df1 |> 
  full_join (df3, by = "rid") # df1 and df3

dfm2 <- dfscores |> 
  full_join(df8, by = "rid") # dfscores and df8

df_combined <- dfm1 |> 
  full_join(dfm2, by = "rid") # dfm1 and dfm2, which are the merged dataframes

Getting Column Names

cat(colnames(df_combined), sep = ", ")
rid, w1status, w1timestamp, w1duplicate, w1timetaken, w1testdata, w1country, w1regionstamp, w1blockorder, w1questionorder, w1participation, w1imagetimer, w1imageinstructions, w1imageexp, w1imagecontrol, w1imageitems1, w1imageitems2, w1imageitems3, w1imageitems4, w1imageitems5, w1imageitems6, w1imageitems7, w1imageitems8, w1imageitems9, w1imageitems10, w1imagedog, w1dogcolor, w1imageconf, w1memoryconf, w1tsq1, w1tsq2, w3tsq3, w1tsq3, w1tsq4, w3tsq4, w1tsq5, w1tsq6, w3tsq5, w1tsq7, w1tsq8, w3tsq6, w1tsq9, w1tsq10, w3tsq7, w1tsq11, w1tsq12, w3tsq8, w1tsq13, w1tsq14, w1tsqcheck, newsanec, newscontrol, newsshort, newsqual, newsevqual, newsthoughts, newsconv, ps1, ps2, ps3, ps4, ps5, ps6, w1gs1, w1gs2, w1gs3, w1gs4, w1gs5, w1collab1, w1collab2, w1collab3, w1collab4, w1collab5, nfc1, nfc2, nfc3, nfc4, nfc5, nfc6, nfc7, nfc8, nfc9, nfc10, proc1, proc2, proc3, proc4, proc5, w1commitnum, w1commithrs, w1commitoverw, w1freetime, bigf1, bigf2, bigf3, bigf4, bigf5, bigf6, bigf7, bigf8, bigf9, bigf10, achmot1, achmot2, achmot3, achmot4, achmot5, achmot6, achmot7, achmot8, achmot9, achmot10, achmot11, achmot12, achmotcheck, w1mathse1, w1mathse2, w1mathse3, w1mathse4, w1mathse5, w1mathse6, w1mathse7, w1mathse8, w1mathse9, w1mathse10, w1mathse11, w1mathse12, w1mathse13, w1mathse14, w1mathse15, w1mathax1, w1mathax2, w1mathax3, w1mathax4, w1mathax5, w1mathax6, w1mathax7, w1mathax8, w1mathax9, w1mathaxcheck, w1mw1, w1mw2, w1mw3, w1mw4, w1mw5, age, gendermale, genderfemal, gendernonbinary, genderthird, gendernoid, genderrefuse, ushome, country, w1math1, w1math2, w1math3, w1math4, w1math5, w1math6, w1math7, w1math8, w1math9, w1math10, w1colmath1, w1colmath2, w1colmath3, w1colmath4, w1colmath5, w1colmath6, w1colmath7, w1colmath8, w1colmath9, w1colmath10, w1colmath11, w1colmath12, w1colmath13, w1colmath14, w1colmath15, w1colmath16, w1colmath17, w1colmath18, w1colmath19, w1colmath20, w1colmath21, w1colmath22, w1colmath23, w1colmath24, w1colmath25, w1colmath26, w1colmath27, w1colmath28, w1colmath29, w1colmath30, w1colmath31, w1colstats1, w1colstats2, w1colstats3, w1colstats4, w1colstats5, w1colstats6, w1colstats7, w1colstats8, w1colstats9, w1educ1, w1weduc2, w3stress, w3stressmathp, w3stressamount, w3stressunder, w3stressscore, w3streefinish, w3wander1, w3wander2, w3wander3, w3wander4, mathscore, w8status, w8ts, w8duplicate, w8timetaken, w8ma1, w8ma2, w8mahelpful1, w8mahelpful2, w8mahelpful3, w8mahelpful4, w8aifeelings, w8aienjoy, w8aidislike, w8optimism, w8pride, w8confidence, w8boredom, w8irritation, w8anger, w8annoyance, w8nointerest, w8shame, w8panic, w8embarrassement, w8anxiety, w8curiosity, w8excitement, w8relief, w8empowerment, w8satisfaction, w8interest, w8confusion, w8skepticism, w8guilt, w8overwhelmed, w8disappointment, w8distruct, w8fear, w8regret, w8motivation, w8gratitude, w8distraction

Data Selection

Selecting variables related to math anxiety study

df_subset <- df_combined |> 
  select(w1mathse1, w1mathse2, w1mathse3, w1mathse4, w1mathse5, w1mathse6, 
         w1mathse7, w1mathse8, w1mathse9, w1mathse10, w1mathse11, w1mathse12, 
         w1mathse13, w1mathse14, w1mathse15, 
         w1mathax1, w1mathax2, w1mathax3, w1mathax4, w1mathax5, w1mathax6, 
         w1mathax7, w1mathax8, w1mathax9, w1mathaxcheck, 
         w1mw1, w1mw2, w1mw3, w1mw4, w1mw5, 
         age, gendermale, genderfemal, gendernonbinary, genderthird, gendernoid,
         genderrefuse, 
         w1math1, w1math2, w1math3, w1math4, w1math5, w1math6, w1math7, w1math8, 
         w1math9, w1math10, 
         w1colmath1, w1colmath2, w1colmath3, w1colmath4, w1colmath5, w1colmath6, 
         w1colmath7, w1colmath8, w1colmath9, w1colmath10, w1colmath11, 
         w1colmath12, w1colmath13, w1colmath14, w1colmath15, w1colmath16, 
         w1colmath17, w1colmath18, w1colmath19, w1colmath20, w1colmath21, 
         w1colmath22, w1colmath23, w1colmath24, w1colmath25, w1colmath26, 
         w1colmath27, w1colmath28, w1colmath29, w1colmath30, w1colmath31, 
         w1colstats1, w1colstats2, w1colstats3, w1colstats4, w1colstats5, 
         w1colstats6, w1colstats7, w1colstats8, w1colstats9, w1educ1, w1weduc2,
         w3stress, w3stressmathp, w3stressamount, w3stressunder, w3stressscore, 
         w3streefinish, w3wander1, w3wander2, w3wander3, w3wander4, 
         mathscore, 
         w8status, w8ts, w8duplicate, w8timetaken, w8ma1, w8ma2, w8mahelpful1, 
         w8mahelpful2, w8mahelpful3, w8mahelpful4, w8aifeelings, w8aienjoy, 
         w8aidislike, w8optimism, w8pride, w8confidence, w8boredom, 
         w8irritation, w8anger, w8annoyance, w8nointerest, w8shame, w8panic, 
         w8embarrassement, w8anxiety, w8curiosity, w8excitement, w8relief, 
         w8empowerment, w8satisfaction, w8interest, w8confusion, w8skepticism, 
         w8guilt, w8overwhelmed, w8disappointment, w8distruct, w8fear, 
         w8regret, w8motivation, w8gratitude, w8distraction
         )

Data Filtering

getting quoted column names for filtering

cat(shQuote(colnames(df_combined)), sep = ", ")
'rid', 'w1status', 'w1timestamp', 'w1duplicate', 'w1timetaken', 'w1testdata', 'w1country', 'w1regionstamp', 'w1blockorder', 'w1questionorder', 'w1participation', 'w1imagetimer', 'w1imageinstructions', 'w1imageexp', 'w1imagecontrol', 'w1imageitems1', 'w1imageitems2', 'w1imageitems3', 'w1imageitems4', 'w1imageitems5', 'w1imageitems6', 'w1imageitems7', 'w1imageitems8', 'w1imageitems9', 'w1imageitems10', 'w1imagedog', 'w1dogcolor', 'w1imageconf', 'w1memoryconf', 'w1tsq1', 'w1tsq2', 'w3tsq3', 'w1tsq3', 'w1tsq4', 'w3tsq4', 'w1tsq5', 'w1tsq6', 'w3tsq5', 'w1tsq7', 'w1tsq8', 'w3tsq6', 'w1tsq9', 'w1tsq10', 'w3tsq7', 'w1tsq11', 'w1tsq12', 'w3tsq8', 'w1tsq13', 'w1tsq14', 'w1tsqcheck', 'newsanec', 'newscontrol', 'newsshort', 'newsqual', 'newsevqual', 'newsthoughts', 'newsconv', 'ps1', 'ps2', 'ps3', 'ps4', 'ps5', 'ps6', 'w1gs1', 'w1gs2', 'w1gs3', 'w1gs4', 'w1gs5', 'w1collab1', 'w1collab2', 'w1collab3', 'w1collab4', 'w1collab5', 'nfc1', 'nfc2', 'nfc3', 'nfc4', 'nfc5', 'nfc6', 'nfc7', 'nfc8', 'nfc9', 'nfc10', 'proc1', 'proc2', 'proc3', 'proc4', 'proc5', 'w1commitnum', 'w1commithrs', 'w1commitoverw', 'w1freetime', 'bigf1', 'bigf2', 'bigf3', 'bigf4', 'bigf5', 'bigf6', 'bigf7', 'bigf8', 'bigf9', 'bigf10', 'achmot1', 'achmot2', 'achmot3', 'achmot4', 'achmot5', 'achmot6', 'achmot7', 'achmot8', 'achmot9', 'achmot10', 'achmot11', 'achmot12', 'achmotcheck', 'w1mathse1', 'w1mathse2', 'w1mathse3', 'w1mathse4', 'w1mathse5', 'w1mathse6', 'w1mathse7', 'w1mathse8', 'w1mathse9', 'w1mathse10', 'w1mathse11', 'w1mathse12', 'w1mathse13', 'w1mathse14', 'w1mathse15', 'w1mathax1', 'w1mathax2', 'w1mathax3', 'w1mathax4', 'w1mathax5', 'w1mathax6', 'w1mathax7', 'w1mathax8', 'w1mathax9', 'w1mathaxcheck', 'w1mw1', 'w1mw2', 'w1mw3', 'w1mw4', 'w1mw5', 'age', 'gendermale', 'genderfemal', 'gendernonbinary', 'genderthird', 'gendernoid', 'genderrefuse', 'ushome', 'country', 'w1math1', 'w1math2', 'w1math3', 'w1math4', 'w1math5', 'w1math6', 'w1math7', 'w1math8', 'w1math9', 'w1math10', 'w1colmath1', 'w1colmath2', 'w1colmath3', 'w1colmath4', 'w1colmath5', 'w1colmath6', 'w1colmath7', 'w1colmath8', 'w1colmath9', 'w1colmath10', 'w1colmath11', 'w1colmath12', 'w1colmath13', 'w1colmath14', 'w1colmath15', 'w1colmath16', 'w1colmath17', 'w1colmath18', 'w1colmath19', 'w1colmath20', 'w1colmath21', 'w1colmath22', 'w1colmath23', 'w1colmath24', 'w1colmath25', 'w1colmath26', 'w1colmath27', 'w1colmath28', 'w1colmath29', 'w1colmath30', 'w1colmath31', 'w1colstats1', 'w1colstats2', 'w1colstats3', 'w1colstats4', 'w1colstats5', 'w1colstats6', 'w1colstats7', 'w1colstats8', 'w1colstats9', 'w1educ1', 'w1weduc2', 'w3stress', 'w3stressmathp', 'w3stressamount', 'w3stressunder', 'w3stressscore', 'w3streefinish', 'w3wander1', 'w3wander2', 'w3wander3', 'w3wander4', 'mathscore', 'w8status', 'w8ts', 'w8duplicate', 'w8timetaken', 'w8ma1', 'w8ma2', 'w8mahelpful1', 'w8mahelpful2', 'w8mahelpful3', 'w8mahelpful4', 'w8aifeelings', 'w8aienjoy', 'w8aidislike', 'w8optimism', 'w8pride', 'w8confidence', 'w8boredom', 'w8irritation', 'w8anger', 'w8annoyance', 'w8nointerest', 'w8shame', 'w8panic', 'w8embarrassement', 'w8anxiety', 'w8curiosity', 'w8excitement', 'w8relief', 'w8empowerment', 'w8satisfaction', 'w8interest', 'w8confusion', 'w8skepticism', 'w8guilt', 'w8overwhelmed', 'w8disappointment', 'w8distruct', 'w8fear', 'w8regret', 'w8motivation', 'w8gratitude', 'w8distraction'

Filtering to include only students who answered all week 1 math anxiety questions and who passed the attention check where they had to select 3

ma_w1vars <- c(
  "w1mathse1", "w1mathse2", "w1mathse3", "w1mathse4", "w1mathse5", 
  "w1mathse6", "w1mathse7", "w1mathse8", "w1mathse9", "w1mathse10",
  "w1mathse11", "w1mathse12", "w1mathse13", "w1mathse14", "w1mathse15",
  "w1mathax1", "w1mathax2", "w1mathax3", "w1mathax4", "w1mathax5",
  "w1mathax6", "w1mathax7", "w1mathax8", "w1mathax9", "w1mathaxcheck"
)

df_subset <- df_subset |> 
  filter(if_all(all_of(ma_w1vars), ~ !is.na(.))) |> 
  filter(w1mathaxcheck == 3) # Attention Check 1

Filtering to include only students who answered all week 3 math anxiety questions and week 8 math anxiety with ai and percpetion questions

ma_w38vars <- c('w3stress', 'w3stressmathp', 'w3stressamount', 
                'w3stressunder', 'w3stressscore', 'w3streefinish', 
                'w3wander1', 'w3wander2', 'w3wander3', 'w3wander4', 
                'mathscore', 'w8status', 'w8ts', 'w8duplicate', 
                'w8timetaken', 'w8ma1', 'w8ma2', 'w8mahelpful1', 
                'w8mahelpful2', 'w8mahelpful3', 'w8mahelpful4')

df_subset <- df_subset |> 
  filter(if_all(all_of(ma_w38vars), ~ !is.na(.)))

# We have 73 students with this filtered data

Composite Scores

Getting Column Names

cat(colnames(df_subset), sep = ", ")
w1mathse1, w1mathse2, w1mathse3, w1mathse4, w1mathse5, w1mathse6, w1mathse7, w1mathse8, w1mathse9, w1mathse10, w1mathse11, w1mathse12, w1mathse13, w1mathse14, w1mathse15, w1mathax1, w1mathax2, w1mathax3, w1mathax4, w1mathax5, w1mathax6, w1mathax7, w1mathax8, w1mathax9, w1mathaxcheck, w1mw1, w1mw2, w1mw3, w1mw4, w1mw5, age, gendermale, genderfemal, gendernonbinary, genderthird, gendernoid, genderrefuse, w1math1, w1math2, w1math3, w1math4, w1math5, w1math6, w1math7, w1math8, w1math9, w1math10, w1colmath1, w1colmath2, w1colmath3, w1colmath4, w1colmath5, w1colmath6, w1colmath7, w1colmath8, w1colmath9, w1colmath10, w1colmath11, w1colmath12, w1colmath13, w1colmath14, w1colmath15, w1colmath16, w1colmath17, w1colmath18, w1colmath19, w1colmath20, w1colmath21, w1colmath22, w1colmath23, w1colmath24, w1colmath25, w1colmath26, w1colmath27, w1colmath28, w1colmath29, w1colmath30, w1colmath31, w1colstats1, w1colstats2, w1colstats3, w1colstats4, w1colstats5, w1colstats6, w1colstats7, w1colstats8, w1colstats9, w1educ1, w1weduc2, w3stress, w3stressmathp, w3stressamount, w3stressunder, w3stressscore, w3streefinish, w3wander1, w3wander2, w3wander3, w3wander4, mathscore, w8status, w8ts, w8duplicate, w8timetaken, w8ma1, w8ma2, w8mahelpful1, w8mahelpful2, w8mahelpful3, w8mahelpful4, w8aifeelings, w8aienjoy, w8aidislike, w8optimism, w8pride, w8confidence, w8boredom, w8irritation, w8anger, w8annoyance, w8nointerest, w8shame, w8panic, w8embarrassement, w8anxiety, w8curiosity, w8excitement, w8relief, w8empowerment, w8satisfaction, w8interest, w8confusion, w8skepticism, w8guilt, w8overwhelmed, w8disappointment, w8distruct, w8fear, w8regret, w8motivation, w8gratitude, w8distraction

Week 1 Math Self-Efficacy

df_subset <- df_subset |> 
  rowwise() |> 
  mutate(
    w1mse_sum = sum(c_across(w1mathse1:w1mathse15)),
    w1mse_mean = mean(c_across(w1mathse1:w1mathse15))
  ) |> 
  ungroup()
skim(df_subset$w1mse_mean)
Data summary
Name df_subset$w1mse_mean
Number of rows 70
Number of columns 1
_______________________
Column type frequency:
numeric 1
________________________
Group variables None

Variable type: numeric

skim_variable n_missing complete_rate mean sd p0 p25 p50 p75 p100 hist
data 0 1 2.76 0.84 1.07 2.13 2.87 3.4 4.87 ▃▇▇▆▁
df_subset |> 
  ggplot(aes(x = w1mse_mean)) + geom_histogram(bins = 30)

Week 1 Math Anxiety (Trait)

df_subset <- df_subset |> 
  rowwise() |> 
  mutate(
    w1max_sum = sum(c_across(w1mathax1:w1mathax9)),
    w1max_mean = mean(c_across(w1mathax1:w1mathax9))
  ) |> 
  ungroup()
df_subset |> 
  ggplot(aes(x = w1max_mean)) + geom_histogram(bins = 30)

df_subset |> 
  ggplot(aes(x = w1mse_mean, y = w1max_mean)) + geom_point()+
    geom_smooth(method = "lm", color = "blue") +
  stat_cor(aes(label = ..r.label..), label.x = 1, label.y = 6) 
Warning: The dot-dot notation (`..r.label..`) was deprecated in ggplot2 3.4.0.
ℹ Please use `after_stat(r.label)` instead.
`geom_smooth()` using formula = 'y ~ x'

Week 3 Math Aniety (State)

df_subset <- df_subset |> 
  rowwise() |> 
  mutate(
    w3max_sum = sum(c_across(w3stress:w3streefinish)),
    w3max_mean = mean(c_across(w3stress:w3streefinish))
  ) |> 
  ungroup()
df_subset |> 
  ggplot(aes(x = w3max_mean)) + geom_histogram(bins = 30)

df_subset |> 
  ggplot(aes(y = w3max_mean, x = w1max_mean)) + geom_point() +
    geom_smooth(method = "lm", color = "blue") +
  stat_cor(aes(label = ..r.label..), label.x = 1.8, label.y = 4.7) 
`geom_smooth()` using formula = 'y ~ x'

Week 3 Math Score

df_subset |> 
  ggplot(aes(x = mathscore)) + geom_histogram(bins = 30)

Correlation between trait math anxiety and math score

df_subset |> 
  ggplot(aes(y = mathscore, x = w1max_mean)) + geom_point() +
    geom_smooth(method = "lm", color = "blue") +
  stat_cor(aes(label = ..r.label..), label.x = 1.8, label.y = 4.7) 
`geom_smooth()` using formula = 'y ~ x'

Correlation between state math anxiety and math score

df_subset |> 
  ggplot(aes(y = mathscore, x = w3max_mean)) + geom_point() +
    geom_smooth(method = "lm", color = "blue") +
  stat_cor(aes(label = ..r.label..), label.x = 1.8, label.y = 4.7) 
`geom_smooth()` using formula = 'y ~ x'

Week 8 Math Anxiety While using AI as Tutor

df_subset <- df_subset |> 
  rowwise() |> 
  mutate(
    w8max_sum = sum(c_across(w8ma1:w8ma2)),
    w8max_mean = mean(c_across(w8ma1:w8ma2))
  ) |> 
  ungroup()

Math Anxiety while using AI is lower than trait and state math anxiety.

df_subset |> 
  ggplot(aes(x = w8max_mean)) + geom_histogram(bins = 30)

State math anxiety is positively related to math anxiety while using the AI tutor, opposite of our predicted direction. We thought state math anxiety would be unrelated or negatively related to math anxiety while using AI tutor, as we expected anxious students to have reduced anxiety if using AI.

df_subset |> 
  ggplot(aes(y = w8max_mean, x = w3max_mean)) + geom_point() +
    geom_smooth(method = "lm", color = "blue") +
    stat_cor(aes(label = ..r.label..), label.x = 1.8, label.y = 4.7) 
`geom_smooth()` using formula = 'y ~ x'

Week 8 Math Helpfulness of AI

df_subset <- df_subset |> 
  rowwise() |> 
  mutate(
    w8aihelp_sum = sum(c_across(w8mahelpful1:w8mahelpful4)),
    w8aihelp_mean = mean(c_across(w8mahelpful1:w8mahelpful4))
  ) |> 
  ungroup()
df_subset |> 
  ggplot(aes(x = w8aihelp_mean)) + geom_histogram(bins = 30)

Those with higher math anxiety while using tutor are less likely to find the AI helpful. There seems to be a negative sentiment towards using AI when reviewing and correcting one’s work.

df_subset |> 
  ggplot(aes(x = w8max_mean, y = mathscore)) +
  geom_point(alpha = 0.3) +
  geom_smooth(method = "lm", color = "blue") +
    stat_cor(aes(label = ..r.label..), label.x = 1.8, label.y = 4.7) 
`geom_smooth()` using formula = 'y ~ x'

How does math scores moderate helpfulness of using AI?

Trait-level math anxeity did not predict helpfulness of using AI

State-level math anxiety did. Higher state-level anxiety predicted finding the AI tutor more helpful.

Math scores also positive predicted rating the AI helpufl.

No interaction (moderation) between state-level math anxiety and math scores on AI helpfulness.

lmresults <- lm(w8aihelp_mean ~ w1max_mean + w3max_mean*mathscore, df_subset)

summary(lmresults)

Call:
lm(formula = w8aihelp_mean ~ w1max_mean + w3max_mean * mathscore, 
    data = df_subset)

Residuals:
     Min       1Q   Median       3Q      Max 
-1.95075 -0.44372  0.06902  0.50591  1.86738 

Coefficients:
                     Estimate Std. Error t value Pr(>|t|)  
(Intercept)          -0.54181    1.46447  -0.370   0.7126  
w1max_mean            0.16083    0.12967   1.240   0.2193  
w3max_mean            0.85476    0.41192   2.075   0.0419 *
mathscore             0.29890    0.14682   2.036   0.0458 *
w3max_mean:mathscore -0.07538    0.04300  -1.753   0.0843 .
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 0.7828 on 65 degrees of freedom
Multiple R-squared:  0.1095,    Adjusted R-squared:  0.05475 
F-statistic: 1.999 on 4 and 65 DF,  p-value: 0.1051