Doggo/Nogo (Study 1) - Data Cleaning

Data Preparation

Code
library(tidyverse)
library(easystats)
library(patchwork)
library(ggside)
dfsub <- read.csv("../data/rawdata_participants.csv") 
df <- read.csv("../data/rawdata_game.csv") 

The initial sample consisted of 25 participants (Mean age = 24.3, SD = 6.5, range: [18, 48]; Gender: 56.0% women, 36.0% men, 8.00% non-binary; Education: Bachelor, 80.00%; Doctorate, 8.00%; High school, 4.00%; Master, 8.00%).

Code
# Feedback computation
newdf <- data.frame()
for(i in unique(df$Participant)) {
  for(s in unique(df$Session)) {
    dat <- df[df$Participant == i & df$Session == s, ]
    dat$Feedback <- c("Positive", ifelse(dat$RT <= dat$Threshold, "Positive", "Negative")[2:nrow(dat)])
  
    n_positive <- c(0)
    n_negative <- c(0)
    counter_positive <- 0
    counter_negative <- 0
    for(j in 2:nrow(dat)) {
      prev_feedback <- dat$Feedback[j-1]
      current_feedback <- dat$Feedback[j]
  
      if(prev_feedback == "Positive") {
        counter_positive <- counter_positive + 1
      } else {
        counter_positive <- 0
      }
      n_positive <- c(n_positive, counter_positive)
  
      if(prev_feedback == "Negative") {
        counter_negative <- counter_negative + 1
      } else {
        counter_negative <- 0
      }
      n_negative <- c(n_negative, counter_negative)
    }
    dat$Feedback_N_Positive <- n_positive
    dat$Feedback_N_Negative <- n_negative
    newdf <- rbind(newdf, dat)
  }
}
df <- newdf

Recruitment History

Code
# Consecutive count of participants per day (as area)
dfsub |>
  mutate(Date = as.Date(Date, format = "%d/%m/%Y")) |> 
  group_by(Date) |> 
  summarize(N = n()) |> 
  ungroup() |>
  mutate(N = cumsum(N)) |>
  ggplot(aes(x = Date, y = N)) +
  geom_area() +
  scale_y_continuous(expand = c(0, 0)) +
  labs(
    title = "Recruitment History",
    x = "Date",
    y = "Total Number of Participants"
  ) +
  see::theme_modern()

Manipulation Check

ISI

df |> 
  ggplot(aes(x=ISI, y=RT)) +
  geom_point2(alpha=1/10, size=3) +
  geom_smooth(method = "gam", formula = y ~ s(x, bs = "cs"), se = FALSE, linewidth=2) +
  scale_y_log10() +
  theme_minimal() +
  coord_cartesian(ylim = c(0.1, 1))

Threshold

cumulative_median <- function(x) {
  sapply(seq_along(x), function(i) median(x[1:i]))
}

df |> 
  arrange(Participant, Session, Trial) |> 
  group_by(Participant, Session) |> 
  mutate(CumMedian = cumulative_median(RT)) |> 
  ungroup() |> 
  ggplot(aes(x=Threshold, y=CumMedian)) +
  geom_abline(intercept = 0, slope = 1) +
  geom_point(aes(color=Participant)) +
  facet_grid(~Session) +
  scale_x_log10() +
  scale_y_log10() 
Warning: Removed 50 rows containing missing values or values outside the scale range
(`geom_point()`).

Feedback

df |>
  filter(RT < 1) |> 
  mutate(Feedback_N_Positive = ifelse(Feedback_N_Positive > 5, 6, Feedback_N_Positive),
         Feedback_N_Negative = ifelse(Feedback_N_Negative > 3, 4, Feedback_N_Negative)) |>
  ggplot(aes(x=Feedback_N_Positive, y=RT)) +
  geom_smooth(method="lm", formula="y~poly(x, 2)") +
  ggdist::stat_halfeye(aes(group=interaction(as.factor(Feedback_N_Positive), as.factor(Feedback_N_Negative)),
                           fill=as.factor(Feedback_N_Negative)), alpha=1/3) +
  scale_y_log10() +
  coord_cartesian(ylim = c(0.125, 0.875))

# t.test(RT ~ FeedbackN1, data = filter(!is.na(FeedbackN1)))
# m <- glmmTMB::glmmTMB(RT ~ Feedback_Negative + (1|Participant), 
#                       data=df |> 
#                         mutate(Feedback_Negative = ifelse(Feedback_N_Negative == 1, 
#                                                           "True",
#                                                           ifelse(Feedback_N_Positive >= 1,
#                                                                  "False", 
#                                                                  NA))) |> 
#                         filter(!is.na(Feedback_Negative)))

m <- glmmTMB::glmmTMB(
  RT ~ Feedback_Negative + (Feedback_Negative|Participant), 
  data=mutate(df, Feedback_Negative = ifelse(Feedback_N_Negative >= 1, "True", "False")))

parameters::parameters(m, effects="fixed")
# Fixed Effects

Parameter                | Coefficient |       SE |       95% CI |     z |      p
---------------------------------------------------------------------------------
(Intercept)              |        0.30 | 6.22e-03 | [0.29, 0.31] | 48.54 | < .001
Feedback Negative [True] |        0.02 | 3.67e-03 | [0.01, 0.03] |  4.93 | < .001

Uncertainty intervals (equal-tailed) and p-values (two-tailed) computed
  using a Wald z-distribution approximation.
modelbased::estimate_means(m, at = c("Feedback_Negative")) |>
  ggplot(aes(x=Feedback_Negative, y=Mean)) +
  geom_line(aes(group=1)) +
  geom_pointrange(aes(ymin=CI_low, ymax=CI_high)) +
  theme_minimal()

Exclusion

Trials

d <- bayestestR::estimate_density(df$RT, method="KernSmooth")
dsub <- bayestestR::estimate_density(df, select="RT", at=c("Participant", "Session"), method="KernSmooth")

d |>
  ggplot(aes(x=x, y=y)) +
  geom_vline(xintercept = c(0.125, 0.875), linetype = "dashed") +
  geom_area(fill="grey") +
  geom_line(data=dsub, aes(color=Participant, linetype=Session), linewidth=1) +
  coord_cartesian(xlim = c(0, 1)) +
  theme_minimal()

outliers <- (df$RT > 0.875) | (df$RT < 0.125)
df <- df[!outliers, ]

Outlier trials were removed from the dataset (1.80%).

Save

write.csv(df, "../data/data_game.csv", row.names = FALSE)
write.csv(dfsub, "../data/data_participants.csv", row.names = FALSE)