Go/No Go - D-prime

library(splithalfr)

This vignette describes the d-prime; a scoring method introduced by Miller (1996).


Dataset

Load the included Go/No Go dataset and inspect its documentation.

data("ds_gng", package = "splithalfr")
?ds_gng

Relevant variables

The columns used in this example are:

Counterbalancing

The variables condition and stim were counterbalanced. Below we illustrate this for the first participant.

ds_1 <- subset(ds_gng, participant  == 1)
table(ds_1$condition, ds_1$stim)


Scoring the Go/No Go

Scoring function

The scoring function receives the data from a single participant. For the proportion of hits and false alarms, it calculates their quantiles given a standard normal distribution. Extreme values are adjusted for via the log-linear approach (Hautus, 1995).

fn_score <- function(ds) {
  n_hit <- sum(ds$condition == 0 & ds$response == 1)
  n_miss <- sum(ds$condition == 0 & ds$response == 0)
  n_cr <- sum(ds$condition == 2 & ds$response == 1)
  n_fa <- sum(ds$condition == 2 & ds$response == 0)
  p_hit <- (n_hit + 0.5) / ((n_hit + 0.5) + n_miss + 1)
  p_fa <- (n_fa + 0.5) / ((n_fa + 0.5) + n_cr + 1)  
  return (qnorm(p_hit) - qnorm(p_fa))
}

Scoring a single participant

Let’s calculate the d-prime score for the participant with UserID 1.

fn_score(subset(ds_gng, participant == 1))

Scoring all participants

To calculate the d-prime score for each participant, we will use R’s native by function and convert the result to a data frame.

scores <- by(
  ds_gng,
  ds_gng$participant,
  fn_score
)
data.frame(
  participant = names(scores),
  score = as.vector(scores)
)


Estimating split-half reliability

Calculating split scores

To calculate split-half scores for each participant, use the function by_split. The first three arguments of this function are the same as for by. An additional set of arguments allow you to specify how to split the data and how often. In this vignette we will calculate scores of 1000 permutated splits. The trial properties condition and stim were counterbalanced in the Go/No Go design. We will stratify splits by these trial properties. See the vignette on splitting methods for more ways to split the data.

The by_split function returns a data frame with the following columns:

Calculating the split scores may take a while. By default, by_split uses all available CPU cores, but no progress bar is displayed. Setting ncores = 1 will display a progress bar, but processing will be slower.

split_scores <- by_split(
  ds_gng,
  ds_gng$participant,
  fn_score,
  replications = 1000,
  stratification = paste(ds_gng$condition, ds_gng$stim)
)

Calculating reliability coefficients

Next, the output of by_split can be analyzed in order to estimate reliability. By default, functions are provided that calculate Spearman-Brown adjusted Pearson correlations (spearman_brown), Flanagan-Rulon (flanagan_rulon), Angoff-Feldt (angoff_feldt), and Intraclass Correlation (short_icc) coefficients. Each of these coefficient functions can be used with split_coef to calculate the corresponding coefficients per split, which can then be plotted or averaged, for instance via a simple mean.

# Spearman-Brown adjusted Pearson correlations per replication
coefs <- split_coefs(split_scores, spearman_brown)
# Distribution of coefficients
hist(coefs)
# Mean of coefficients
mean(coefs)

Calculating bootstrapped confidence intervals for population reliability coefficient

Finally, we can estimate the Calculate bootstrapped confidence intervals for the value of the reliability coefficient in the population by bootstrapping participants. For this, we’ll need to repeatedly sample participants from the population, calculate a collection of reliability coefficients between the split scores of that sample of participants, and average those coefficients together. Hence, the call to split_ci below, takes (1) the split scores produced by calling by_split (split_scores), (2) the reliability coefficient we used above (spearman_brown), and (3) the method for averaging coefficients we used above (mean).

The bootstrap can take even longer than the split, and doesn’t show any progress bar, but it also uses all available CPU cores by default.

# Conduct a bootstrap (of participants)
bootstrap_result <- split_ci(split_scores, spearman_brown, mean)
# Report confidence intervals
library(boot)
print(boot.ci(bootstrap_result, type="bca"))