feltzzarpentine2010knowmattersless
/data/papers/feltzzarpentine2010knowmattersless/analysis/effect_sizes.qmd
---
title: "Effect size computation: feltzzarpentine2010knowmattersless"
format:
  html:
    toc: true
execute:
  echo: true
  warning: true
  message: false
---

## Shared helpers

```{r}
stop_if_missing <- function(x, name) {
  if (is.na(x)) stop(sprintf("Missing required input: %s", name), call. = FALSE)
}

# Exact small-sample correction factor used by metafor (.cmicalc).
hedges_correction <- function(df) {
  ifelse(df <= 1, NA_real_, exp(lgamma(df/2) - log(sqrt(df/2)) - lgamma((df - 1)/2)))
}

pooled_sd <- function(n_high, n_low, sd_high, sd_low) {
  sqrt(((n_high - 1) * sd_high^2 + (n_low - 1) * sd_low^2) / (n_high + n_low - 2))
}

d_from_groups_independent <- function(n_high, n_low, mean_high, mean_low, sd_high, sd_low) {
  s <- pooled_sd(n_high, n_low, sd_high, sd_low)
  (mean_low - mean_high) / s
}

var_d_independent <- function(d, n_high, n_low) {
  n <- n_high + n_low
  (n / (n_high * n_low)) + (d^2 / (2 * (n - 2)))
}

compute_effect_size <- function(
    paper_key,
    study_id,
    effect_id,
    method_used,
    sign_convention = "d = mean(low) - mean(high)",
    n_high = NA_integer_,
    n_low = NA_integer_,
    mean_high = NA_real_,
    mean_low = NA_real_,
    sd_high = NA_real_,
    sd_low = NA_real_,
    notes_on_assumptions = "",
    imputed_flag = FALSE,
    needs_sensitivity = TRUE
) {
  d <- NA_real_
  v <- NA_real_
  g <- NA_real_
  v_g <- NA_real_
  computed_from_suggested <- NA_character_
  design_used <- if (startsWith(method_used, "between_")) "Between-Subjects" else NA_character_

  if (method_used == "between_groups") {
    computed_from_suggested <- "groups"
    stop_if_missing(n_high, "n_high")
    stop_if_missing(n_low, "n_low")
    stop_if_missing(mean_high, "mean_high")
    stop_if_missing(mean_low, "mean_low")
    stop_if_missing(sd_high, "sd_high")
    stop_if_missing(sd_low, "sd_low")
    d <- d_from_groups_independent(n_high, n_low, mean_high, mean_low, sd_high, sd_low)
    v <- var_d_independent(d, n_high, n_low)
    df_used <- n_high + n_low - 2
    J <- hedges_correction(df_used)
    g <- J * d
    v_g <- (J^2) * v
  } else {
    stop(sprintf("Unknown method_used: %s", method_used), call. = FALSE)
  }

  inputs_used <- paste(
    c(
      sprintf("method=%s", method_used),
      sprintf("sign_convention=%s", sign_convention),
      sprintf("n_low=%s", n_low),
      sprintf("n_high=%s", n_high),
      sprintf("mean_low=%s", mean_low),
      sprintf("mean_high=%s", mean_high),
      sprintf("sd_low=%s", sd_low),
      sprintf("sd_high=%s", sd_high)
    ),
    collapse = ", "
  )

  audit <- data.frame(
    paper_key = paper_key,
    study_id = study_id,
    effect_id = effect_id,
    design = design_used,
    method_used = method_used,
    computed_from_suggested = computed_from_suggested,
    inputs_used = inputs_used,
    d = d,
    v = v,
    g = g,
    v_g = v_g,
    notes_on_assumptions = notes_on_assumptions,
    imputed_flag = imputed_flag,
    needs_sensitivity = needs_sensitivity
  )

  yaml_snippet <- sprintf(
    "effect_size:\\n  metric: SMD\\n  d: %.12f\\n  v: %.12f\\n  computed_from: %s\\n  needs_review: false\\n  notes: \"%s\"\\n",
    d, v, computed_from_suggested, gsub(pattern = "\"", replacement = "'", x = inputs_used)
  )

  list(audit = audit, yaml_snippet = yaml_snippet)
}
```

## Study 1 (Experiment 1): Stanley bank cases

### Effect s1_e1: High Stakes vs Low Stakes

```{r}
paper_key <- "feltzzarpentine2010knowmattersless"
study_id <- 1
effect_id <- "s1_e1"

inputs <- list(
  n_high = 39L,
  n_low = 34L,
  mean_high = 4.26,
  mean_low = 3.68,
  sd_high = 2.14,
  sd_low = 1.91
)
inputs
```

```{r}
# Original scale: 1 = Strongly Agree ... 7 = Strongly Disagree.
# Reverse-score so higher values indicate stronger agreement (match other extractions).
inputs$mean_high <- 8 - inputs$mean_high
inputs$mean_low <- 8 - inputs$mean_low
inputs
```

```{r}
res_s1_e1 <- compute_effect_size(
  paper_key = paper_key,
  study_id = study_id,
  effect_id = effect_id,
  method_used = "between_groups",
  n_high = inputs$n_high,
  n_low = inputs$n_low,
  mean_high = inputs$mean_high,
  mean_low = inputs$mean_low,
  sd_high = inputs$sd_high,
  sd_low = inputs$sd_low,
  notes_on_assumptions = "Means reverse-scored as (8 - M) because response scale is 1=Strongly Agree ... 7=Strongly Disagree (to align with other extractions where higher=more agreement). Group Ns inferred from total N=152 + reported independent-samples t-test dfs in Notes [6]-[8] (PDF p.17); means/SD from Notes [6]."
)
res_s1_e1$audit
cat(res_s1_e1$yaml_snippet)
```

### Effect s1_e2: Ignorant High Stakes vs Low Stakes

```{r}
paper_key <- "feltzzarpentine2010knowmattersless"
study_id <- 1
effect_id <- "s1_e2"

inputs <- list(
  n_high = 39L,
  n_low = 34L,
  mean_high = 3.59,
  mean_low = 3.68,
  sd_high = 1.90,
  sd_low = 1.91
)
inputs
```

```{r}
# Original scale: 1 = Strongly Agree ... 7 = Strongly Disagree.
# Reverse-score so higher values indicate stronger agreement (match other extractions).
inputs$mean_high <- 8 - inputs$mean_high
inputs$mean_low <- 8 - inputs$mean_low
inputs
```

```{r}
res_s1_e2 <- compute_effect_size(
  paper_key = paper_key,
  study_id = study_id,
  effect_id = effect_id,
  method_used = "between_groups",
  n_high = inputs$n_high,
  n_low = inputs$n_low,
  mean_high = inputs$mean_high,
  mean_low = inputs$mean_low,
  sd_high = inputs$sd_high,
  sd_low = inputs$sd_low,
  notes_on_assumptions = "Means reverse-scored as (8 - M) because response scale is 1=Strongly Agree ... 7=Strongly Disagree (to align with other extractions where higher=more agreement). Group Ns inferred from total N=152 + reported independent-samples t-test dfs in Notes [6]-[8] (PDF p.17); means/SD from Notes [6]-[7]."
)
res_s1_e2$audit
cat(res_s1_e2$yaml_snippet)
```

### Effect s1_e3: Low Attributer–High Subject Stakes vs Low Stakes

```{r}
paper_key <- "feltzzarpentine2010knowmattersless"
study_id <- 1
effect_id <- "s1_e3"

inputs <- list(
  n_high = 40L,
  n_low = 34L,
  mean_high = 4.75,
  mean_low = 3.68,
  sd_high = 1.89,
  sd_low = 1.91
)
inputs
```

```{r}
# Original scale: 1 = Strongly Agree ... 7 = Strongly Disagree.
# Reverse-score so higher values indicate stronger agreement (match other extractions).
inputs$mean_high <- 8 - inputs$mean_high
inputs$mean_low <- 8 - inputs$mean_low
inputs
```

```{r}
res_s1_e3 <- compute_effect_size(
  paper_key = paper_key,
  study_id = study_id,
  effect_id = effect_id,
  method_used = "between_groups",
  n_high = inputs$n_high,
  n_low = inputs$n_low,
  mean_high = inputs$mean_high,
  mean_low = inputs$mean_low,
  sd_high = inputs$sd_high,
  sd_low = inputs$sd_low,
  notes_on_assumptions = "Means reverse-scored as (8 - M) because response scale is 1=Strongly Agree ... 7=Strongly Disagree (to align with other extractions where higher=more agreement). Group Ns inferred from total N=152 + reported independent-samples t-test dfs in Notes [6]-[8] (PDF p.17); means/SD from Notes [6] and [8]."
)
res_s1_e3$audit
cat(res_s1_e3$yaml_snippet)
```

## Study 2 (Experiment 2): Minimal bridge cases

### Effect s2_e1: Minimal High Stakes vs Minimal Low Stakes

```{r}
paper_key <- "feltzzarpentine2010knowmattersless"
study_id <- 2
effect_id <- "s2_e1"

inputs <- list(
  n_high = 39L,
  n_low = 41L,
  mean_high = 3.23,
  mean_low = 3.29,
  sd_high = 1.58,
  sd_low = 1.76
)
inputs
```

```{r}
# Original scale: 1 = Strongly Agree ... 7 = Strongly Disagree.
# Reverse-score so higher values indicate stronger agreement (match other extractions).
inputs$mean_high <- 8 - inputs$mean_high
inputs$mean_low <- 8 - inputs$mean_low
inputs
```

```{r}
res_s2_e1 <- compute_effect_size(
  paper_key = paper_key,
  study_id = study_id,
  effect_id = effect_id,
  method_used = "between_groups",
  n_high = inputs$n_high,
  n_low = inputs$n_low,
  mean_high = inputs$mean_high,
  mean_low = inputs$mean_low,
  sd_high = inputs$sd_high,
  sd_low = inputs$sd_low,
  notes_on_assumptions = "Means reverse-scored as (8 - M) because response scale is 1=Strongly Agree ... 7=Strongly Disagree (to align with other extractions where higher=more agreement). Group Ns inferred from total N=119 + reported independent-samples t-test dfs in Notes [10]-[11] (PDF p.17); means/SD from Notes [10]."
)
res_s2_e1$audit
cat(res_s2_e1$yaml_snippet)
```

### Effect s2_e2: Minimal High Stakes vs Attributer

```{r}
paper_key <- "feltzzarpentine2010knowmattersless"
study_id <- 2
effect_id <- "s2_e2"

inputs <- list(
  n_high = 39L,
  n_low = 39L,
  mean_high = 3.23,
  mean_low = 3.87,
  sd_high = 1.58,
  sd_low = 1.13
)
inputs
```

```{r}
# Original scale: 1 = Strongly Agree ... 7 = Strongly Disagree.
# Reverse-score so higher values indicate stronger agreement (match other extractions).
inputs$mean_high <- 8 - inputs$mean_high
inputs$mean_low <- 8 - inputs$mean_low
inputs
```

```{r}
res_s2_e2 <- compute_effect_size(
  paper_key = paper_key,
  study_id = study_id,
  effect_id = effect_id,
  method_used = "between_groups",
  n_high = inputs$n_high,
  n_low = inputs$n_low,
  mean_high = inputs$mean_high,
  mean_low = inputs$mean_low,
  sd_high = inputs$sd_high,
  sd_low = inputs$sd_low,
  notes_on_assumptions = "Means reverse-scored as (8 - M) because response scale is 1=Strongly Agree ... 7=Strongly Disagree (to align with other extractions where higher=more agreement). Group Ns inferred from total N=119 + reported independent-samples t-test dfs in Notes [10]-[11] (PDF p.17); means/SD from Notes [10] and [11]."
)
res_s2_e2$audit
cat(res_s2_e2$yaml_snippet)
```

## Study 3 (Experiment 3): Simplified bank cases

### Effect s3_e1: Simplified High Stakes vs Simplified Low Stakes

```{r}
paper_key <- "feltzzarpentine2010knowmattersless"
study_id <- 3
effect_id <- "s3_e1"

inputs <- list(
  n_high = 42L,
  n_low = 40L,
  mean_high = 3.83,
  mean_low = 3.85,
  sd_high = 1.92,
  sd_low = 1.73
)
inputs
```

```{r}
# Original scale: 1 = Strongly Agree ... 7 = Strongly Disagree.
# Reverse-score so higher values indicate stronger agreement (match other extractions).
inputs$mean_high <- 8 - inputs$mean_high
inputs$mean_low <- 8 - inputs$mean_low
inputs
```

```{r}
res_s3_e1 <- compute_effect_size(
  paper_key = paper_key,
  study_id = study_id,
  effect_id = effect_id,
  method_used = "between_groups",
  n_high = inputs$n_high,
  n_low = inputs$n_low,
  mean_high = inputs$mean_high,
  mean_low = inputs$mean_low,
  sd_high = inputs$sd_high,
  sd_low = inputs$sd_low,
  notes_on_assumptions = "Means reverse-scored as (8 - M) because response scale is 1=Strongly Agree ... 7=Strongly Disagree (to align with other extractions where higher=more agreement). Means/SD and t(df) from Notes [14] (PDF p.18). Group Ns inferred from Notes [14] and cross-comparison dfs in Notes [14] and [16] (PDF p.18)."
)
res_s3_e1$audit
cat(res_s3_e1$yaml_snippet)
```

## Study 4 (Experiment 4): High vs low stakes bridge (trucks)

### Effect s4_e1: High Stakes Bridge vs Low Stakes Bridge

```{r}
paper_key <- "feltzzarpentine2010knowmattersless"
study_id <- 4
effect_id <- "s4_e1"

inputs <- list(
  n_high = 70L,
  n_low = 70L,
  mean_high = 3.83,
  mean_low = 3.40,
  sd_high = 1.96,
  sd_low = 1.74
)
inputs
```

```{r}
# Original scale: 1 = Strongly Agree ... 7 = Strongly Disagree.
# Reverse-score so higher values indicate stronger agreement (match other extractions).
inputs$mean_high <- 8 - inputs$mean_high
inputs$mean_low <- 8 - inputs$mean_low
inputs
```

```{r}
res_s4_e1 <- compute_effect_size(
  paper_key = paper_key,
  study_id = study_id,
  effect_id = effect_id,
  method_used = "between_groups",
  n_high = inputs$n_high,
  n_low = inputs$n_low,
  mean_high = inputs$mean_high,
  mean_low = inputs$mean_low,
  sd_high = inputs$sd_high,
  sd_low = inputs$sd_low,
  notes_on_assumptions = "Means reverse-scored as (8 - M) because response scale is 1=Strongly Agree ... 7=Strongly Disagree (to align with other extractions where higher=more agreement). Total N=140 from Experiment 4 text (PDF p.12); means/SD and t(df) from Notes [16] (PDF p.18). Group Ns inferred from Notes [16] cross-comparison dfs (PDF p.18)."
)
res_s4_e1$audit
cat(res_s4_e1$yaml_snippet)
```