Skip to content

Commit 27e9c77

Browse files
BuchBuch
authored andcommitted
added behavioral analysis scripts for error confidence
1 parent 9cd3496 commit 27e9c77

File tree

6 files changed

+623
-93
lines changed

6 files changed

+623
-93
lines changed
Lines changed: 315 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,315 @@
1+
# 03_confidence-ratings.r - error confidence rating analyses
2+
# author: [your name]
3+
4+
# this script assumes it's sourced from batch_behavioral-analyses.r
5+
# with data & directories already loaded
6+
7+
library(tidyverse)
8+
library(ez)
9+
library(effsize)
10+
11+
cat("\n=== CONFIDENCE RATING ANALYSES ===\n")
12+
cat("started:", as.character(Sys.time()), "\n\n")
13+
14+
# create output directory for confidence analyses
15+
confidence_dir <- file.path(session_dir, "confidence_ratings")
16+
dir.create(confidence_dir, showWarnings = FALSE)
17+
18+
# === prepare confidence data ===
19+
prepare_confidence_data <- function(data, condition_type, verbose = TRUE) {
20+
# prepare data for confidence analyses
21+
#
22+
# inputs:
23+
# data - trial-level behavioral data
24+
# condition_type - "visible_correctness", "visible_error_type", or "invisible_response_type"
25+
# verbose - print info
26+
#
27+
# outputs:
28+
# tibble ready for anova
29+
30+
if (condition_type == "visible_correctness") {
31+
# visible: correct vs error × social vs nonsocial
32+
conf_data <- data %>%
33+
filter(
34+
code %in% c(111, 112, 113, 211, 212, 213),
35+
!is.na(confidenceRating)
36+
) %>%
37+
mutate(
38+
subject = factor(subject),
39+
social = factor(ifelse(code %in% c(111, 112, 113), "social", "nonsocial")),
40+
correctness = factor(ifelse(code %in% c(111, 211), "correct", "error"))
41+
) %>%
42+
select(subject, social, correctness, confidenceRating)
43+
44+
} else if (condition_type == "visible_error_type") {
45+
# visible: flanker vs nonflanker error × social vs nonsocial (errors only)
46+
conf_data <- data %>%
47+
filter(
48+
code %in% c(112, 113, 212, 213), # errors only
49+
!is.na(confidenceRating)
50+
) %>%
51+
mutate(
52+
subject = factor(subject),
53+
social = factor(ifelse(code %in% c(112, 113), "social", "nonsocial")),
54+
error_type = factor(ifelse(code %in% c(112, 212), "flanker", "nonflanker"))
55+
) %>%
56+
select(subject, social, error_type, confidenceRating)
57+
58+
} else if (condition_type == "invisible_response_type") {
59+
# invisible: flanker error vs nonflanker guess × social vs nonsocial
60+
conf_data <- data %>%
61+
filter(
62+
code %in% c(102, 104, 202, 204),
63+
!is.na(confidenceRating)
64+
) %>%
65+
mutate(
66+
subject = factor(subject),
67+
social = factor(ifelse(code %in% c(102, 104), "social", "nonsocial")),
68+
response_type = factor(ifelse(code %in% c(102, 202), "flanker_error", "nonflanker_guess"))
69+
) %>%
70+
select(subject, social, response_type, confidenceRating)
71+
}
72+
73+
if (verbose) {
74+
cat(" prepared", nrow(conf_data), "trials for", condition_type, "\n")
75+
}
76+
77+
return(conf_data)
78+
}
79+
80+
# === run confidence analyses ===
81+
82+
# 1. visible: correctness × social
83+
if (CONFIDENCE_ANALYSES$visible_correctness) {
84+
cat("\n1. visible condition: correctness × social\n")
85+
cat(" 2×2 anova: correct/error × social/nonsocial\n")
86+
87+
# prepare data
88+
conf_correctness <- prepare_confidence_data(transformed_data, "visible_correctness")
89+
90+
# calculate descriptives
91+
descriptives_correctness <- conf_correctness %>%
92+
group_by(social, correctness) %>%
93+
summarise(
94+
n = n(),
95+
mean = mean(confidenceRating, na.rm = TRUE),
96+
sd = sd(confidenceRating, na.rm = TRUE),
97+
se = sd / sqrt(n),
98+
.groups = "drop"
99+
)
100+
101+
cat("\n descriptive statistics:\n")
102+
print(descriptives_correctness)
103+
104+
# run 2×2 repeated measures anova
105+
anova_correctness <- ezANOVA(
106+
data = conf_correctness,
107+
dv = confidenceRating,
108+
wid = subject,
109+
within = .(social, correctness),
110+
detailed = TRUE,
111+
type = 3
112+
)
113+
114+
cat("\n anova results:\n")
115+
print(anova_correctness$ANOVA)
116+
117+
# extract ANOVA table & calculate partial eta squared
118+
anova_table_correctness <- anova_correctness$ANOVA %>%
119+
mutate(
120+
partial_eta_sq = SSn / (SSn + SSd)
121+
)
122+
123+
# save results
124+
results_correctness <- list(
125+
descriptives = descriptives_correctness,
126+
anova = anova_correctness,
127+
anova_table = anova_table_correctness,
128+
data = conf_correctness
129+
)
130+
saveRDS(results_correctness, file.path(confidence_dir, "visible_correctness.rds"))
131+
132+
# save tables to tables directory
133+
save_descriptives_table(descriptives_correctness, "confidence_visible_correctness_descriptives", tables_dir)
134+
save_anova_results(anova_table_correctness, "confidence_visible_correctness", tables_dir)
135+
136+
# create plot
137+
plot_path <- file.path(confidence_dir, "confidence_visible_correctness.png")
138+
plot_confidence_interaction(conf_correctness %>%
139+
mutate(is_error = correctness == "error"),
140+
plot_type = "correctness",
141+
save_path = plot_path)
142+
}
143+
144+
# 2. visible: error type × social (errors only)
145+
if (CONFIDENCE_ANALYSES$visible_error_type) {
146+
cat("\n2. visible condition: error type × social (errors only)\n")
147+
cat(" 2×2 anova: flanker/nonflanker × social/nonsocial\n")
148+
149+
# prepare data
150+
conf_error_type <- prepare_confidence_data(transformed_data, "visible_error_type")
151+
152+
# check sample sizes per cell
153+
cell_counts <- conf_error_type %>%
154+
group_by(subject, social, error_type) %>%
155+
summarise(n_trials = n(), .groups = "drop") %>%
156+
group_by(social, error_type) %>%
157+
summarise(n_subjects = n(), .groups = "drop")
158+
159+
cat("\n subjects per cell:\n")
160+
print(cell_counts)
161+
162+
# only run if sufficient data
163+
if (all(cell_counts$n_subjects >= 10)) {
164+
# calculate descriptives
165+
descriptives_error_type <- conf_error_type %>%
166+
group_by(social, error_type) %>%
167+
summarise(
168+
n = n(),
169+
mean = mean(confidenceRating, na.rm = TRUE),
170+
sd = sd(confidenceRating, na.rm = TRUE),
171+
se = sd / sqrt(n),
172+
.groups = "drop"
173+
)
174+
175+
cat("\n descriptive statistics:\n")
176+
print(descriptives_error_type)
177+
178+
# run 2×2 repeated measures anova
179+
anova_error_type <- ezANOVA(
180+
data = conf_error_type,
181+
dv = confidenceRating,
182+
wid = subject,
183+
within = .(social, error_type),
184+
detailed = TRUE,
185+
type = 3
186+
)
187+
188+
cat("\n anova results:\n")
189+
print(anova_error_type$ANOVA)
190+
191+
# extract ANOVA table & calculate partial eta squared
192+
anova_table_error_type <- anova_error_type$ANOVA %>%
193+
mutate(
194+
partial_eta_sq = SSn / (SSn + SSd)
195+
)
196+
197+
# save results
198+
results_error_type <- list(
199+
descriptives = descriptives_error_type,
200+
anova = anova_error_type,
201+
anova_table = anova_table_error_type,
202+
data = conf_error_type
203+
)
204+
saveRDS(results_error_type, file.path(confidence_dir, "visible_error_type.rds"))
205+
206+
# save tables to tables directory
207+
save_descriptives_table(descriptives_error_type, "confidence_visible_error_type_descriptives", tables_dir)
208+
save_anova_results(anova_table_error_type, "confidence_visible_error_type", tables_dir)
209+
210+
# create plot
211+
plot_path <- file.path(confidence_dir, "confidence_visible_error_type.png")
212+
plot_confidence_interaction(conf_error_type %>%
213+
mutate(is_flanker = error_type == "flanker"),
214+
plot_type = "error_type",
215+
save_path = plot_path)
216+
217+
} else {
218+
cat("\n insufficient data for error type analysis\n")
219+
}
220+
}
221+
222+
# 3. invisible: response type × social
223+
if (CONFIDENCE_ANALYSES$invisible_response_type) {
224+
cat("\n3. invisible condition: response type × social\n")
225+
cat(" 2×2 anova: flanker error/nonflanker guess × social/nonsocial\n")
226+
227+
# prepare data
228+
conf_response_type <- prepare_confidence_data(transformed_data, "invisible_response_type")
229+
230+
# calculate descriptives
231+
descriptives_response_type <- conf_response_type %>%
232+
group_by(social, response_type) %>%
233+
summarise(
234+
n = n(),
235+
mean = mean(confidenceRating, na.rm = TRUE),
236+
sd = sd(confidenceRating, na.rm = TRUE),
237+
se = sd / sqrt(n),
238+
.groups = "drop"
239+
)
240+
241+
cat("\n descriptive statistics:\n")
242+
print(descriptives_response_type)
243+
244+
# run 2×2 repeated measures anova
245+
anova_response_type <- ezANOVA(
246+
data = conf_response_type,
247+
dv = confidenceRating,
248+
wid = subject,
249+
within = .(social, response_type),
250+
detailed = TRUE,
251+
type = 3
252+
)
253+
254+
cat("\n anova results:\n")
255+
print(anova_response_type$ANOVA)
256+
257+
# extract ANOVA table & calculate partial eta squared
258+
anova_table_response_type <- anova_response_type$ANOVA %>%
259+
mutate(
260+
partial_eta_sq = SSn / (SSn + SSd)
261+
)
262+
263+
# save results
264+
results_response_type <- list(
265+
descriptives = descriptives_response_type,
266+
anova = anova_response_type,
267+
anova_table = anova_table_response_type,
268+
data = conf_response_type
269+
)
270+
saveRDS(results_response_type, file.path(confidence_dir, "invisible_response_type.rds"))
271+
272+
# save tables to tables directory
273+
save_descriptives_table(descriptives_response_type, "confidence_invisible_response_type_descriptives", tables_dir)
274+
save_anova_results(anova_table_response_type, "confidence_invisible_response_type", tables_dir)
275+
276+
# create plot
277+
plot_path <- file.path(confidence_dir, "confidence_invisible_response_type.png")
278+
plot_confidence_interaction(conf_response_type %>%
279+
mutate(is_flanker_error = response_type == "flanker_error"),
280+
plot_type = "response_type",
281+
save_path = plot_path)
282+
}
283+
284+
# === save summary table ===
285+
cat("\n=== saving confidence rating summary tables ===\n")
286+
287+
# combine all descriptives for summary
288+
all_descriptives <- list()
289+
290+
if (exists("descriptives_correctness")) {
291+
all_descriptives$visible_correctness <- descriptives_correctness %>%
292+
mutate(analysis = "Visible: Correctness")
293+
}
294+
295+
if (exists("descriptives_error_type")) {
296+
all_descriptives$visible_error_type <- descriptives_error_type %>%
297+
mutate(analysis = "Visible: Error Type")
298+
}
299+
300+
if (exists("descriptives_response_type")) {
301+
all_descriptives$invisible_response_type <- descriptives_response_type %>%
302+
mutate(analysis = "Invisible: Response Type")
303+
}
304+
305+
if (length(all_descriptives) > 0) {
306+
summary_table <- bind_rows(all_descriptives) %>%
307+
mutate(across(c(mean, sd, se), ~round(., 3)))
308+
309+
# save as csv
310+
write_csv(summary_table, file.path(tables_dir, "confidence_summary.csv"))
311+
cat(" summary table saved to confidence_summary.csv\n")
312+
}
313+
314+
cat("\n=== confidence rating analyses complete ===\n")
315+
cat("results saved to:", confidence_dir, "\n")

0 commit comments

Comments
 (0)