Skip to content

[BUG] Two distinct bugs identified in the correlation package when using method = "biserial" #372

Description

@maximejollivet

Bug #1.vartype() crashes with NA values in continuous variable

Location

correlation::cor_test().cor_test_biserial().vartype()

Description

In .vartype(), the line :

if (all(x%%1 == 0)) {
  out$is_count <- TRUE
}

x%%1 produces NA for any NA element in x, causing all() to return NA instead of TRUE/FALSE, which triggers the error :

Error in if (all(x%%1 == 0)) { : 
  missing value where TRUE/FALSE needed

This happens when the continuous variable contains at least one NA, which is a common real-world scenario.

Reproducible example

library(correlation)

set.seed(42)
df <- data.frame(
  continuous = c(1, -2, -2, 0, -2, 1, NA, 1, 1, -1,   # contains one NA
                 2,  1,  1, -3, 2,  2,  1, 2, 2, -2),
  binary     = c(0,  1,  0, 1,  0, 1,  0, 1, 0,  1,
                 0,  1,  0,  1, 0,  1,  0, 1, 0,  1)
)

# Triggers: "Error in if (all(x%%1 == 0))"
cor_test(df, x = "continuous", y = "binary", method = "biserial")

Expected behaviour

The function should handle NA values gracefully. The fix is straightforward :

# Current (buggy) code
if (all(x%%1 == 0)) {
  out$is_count <- TRUE
}

# Proposed fix
if (all(x%%1 == 0, na.rm = TRUE)) {
  out$is_count <- TRUE
}

Bug #2correlation() fails when data2 contains a binary variable and data contains multiple variables

Location

correlation::correlation().correlation().cor_test_biserial()

Description

When calling correlation() with data2 containing a single binary variable and data containing multiple continuous variables, .correlation() internally merges both datasets via cbind(data, data2) and then iterates over all pairwise combinations, including pairs of two continuous variables and pairs of two binary variables. When .cor_test_biserial() receives a pair that does not satisfy the "one binary + one continuous" constraint, it throws :

Error: Biserial and point-biserial correlations can only be applied for 
one dichotomous and one continuous variables.

This makes it impossible to use the intended workflow of correlating a set of continuous variables against a single binary variable via data2.

Reproducible example

library(correlation)

set.seed(42)
n <- 30

df_continuous <- data.frame(
  var1 = rnorm(n),
  var2 = rnorm(n),
  var3 = rnorm(n)
)

df_binary <- data.frame(
  binary = sample(0:1, n, replace = TRUE)
)

# Intended usage: correlate each continuous variable against the binary one
# Triggers: "Biserial and point-biserial correlations can only be applied 
#            for one dichotomous and one continuous variables."
correlation(
  data  = df_continuous,
  data2 = df_binary,
  method = "biserial"
)

Expected behaviour

When data2 is provided, .correlation() should restrict pairwise combinations to data × data2 pairs only, before calling cor_test(), rather than generating all combinations from the merged dataset and filtering afterwards. The filtering currently occurs after the loop (lines params <- params[!params$Parameter1 %in% names(data2), ]), which is too late to prevent the error inside the loop.

Workaround (until fix is released)

Iterate manually over each variable :

library(correlation)
library(dplyr)

results <- lapply(names(df_continuous), function(var) {
  cor_test(
    data   = cbind(df_continuous[var], df_binary),
    x      = var,
    y      = "binary",
    method = "biserial"
  )
})

do.call(rbind, results)

Environment

R version 4.5.2 (2025-10-31 ucrt)
packageVersion("correlation") 0.8.8

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions