Search code examples
rarraysmatrixversion

Errors in older R package due to class(x) returning, both, matrix and array - is this new?


I am working with an older package called PIMixture (see here) which throws me a lot of errors at various spots of the code. They all look like this or similar (the following lines are actually from the reproducible example):

> library(PIMixture)
> data(PIdata)
> model<-"C_CIN3PLUS+L_CIN3PLUS+R_CIN3PLUS~RES_HPV16"
> fit1<-PIMixture(p.model=model,data=PIdata1, model="logistic-Weibull")
Error in if (class(mat2) == "numeric") { : the condition has length > 1

Upon investigation I found out that

> class(mat2)
[1] "matrix" "array" 

and hence the if clause returns an error. I cannot believe this was an issue when the package was developed because it would have been noticed. Hence I wonder if in earlier versions of R class(mat2) perhaps evaluated to "Matrix" only, hence having length 1. I can apply fixes in the source code of PIMixture that look like this: class(mat2)[1]. Not nice, but then the package works. I wonder if this is issue occurs due to a change in R across versions or why this problem may occur.


Solution

  • The behaviour changed in R version 4.0.0 or 4.2.0, depending on what you consider to be the "change". news(Version == "4.0.0") says:

    matrix objects now also inherit from class "array", so e.g., class(diag(1)) is c("matrix", "array"). This invalidates code incorrectly assuming that class(matrix_obj)) has length one.

    news(Version == "4.2.0") says:

    Calling if() or while() with a condition of length greater than one gives an error rather than a warning. Consequently, environment variable _R_CHECK_LENGTH_1_CONDITION_ no longer has any effect.

    Why not use is.matrix or is.numeric instead? (It is hard to say what test is appropriate without seeing the logic of the function.)

    See also Martin Mächler's blog post from 2019: When you think class(.) == *, think again!