Skip to content

Commit 8c4da14

Browse files
author
maechler
committed
fix cov2cor(m) where diag(V) is <= 0 or NA
git-svn-id: https://svn.r-project.org/R/trunk@85706 00db46b3-68df-0310-9c12-caf00c1e9a41
1 parent 5589189 commit 8c4da14

File tree

3 files changed

+21
-3
lines changed

3 files changed

+21
-3
lines changed

doc/NEWS.Rd

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,10 @@
578578

579579
\item \code{cov2cor(<0x0>)} now works, fixing \PR{18423} thanks to
580580
Mikael Jagan and Elin Warning.
581+
582+
\item \code{cov2cor(<negative diagonal>)} and similar now give one
583+
warning instead of two, with better wording, fixing \PR{18424} thanks
584+
to Mikael Jagan.
581585
}
582586
}
583587
}

src/library/stats/R/cor.R

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -194,9 +194,12 @@ cov2cor <- function(V)
194194
p <- (d <- dim(V))[1L]
195195
if(!is.numeric(V) || length(d) != 2L || p != d[2L])
196196
stop("'V' is not a square numeric matrix")
197-
Is <- sqrt(1/diag(V)) # diag( 1/sigma_i )
198-
if(any(!is.finite(Is)))
199-
warning("diag(.) had 0 or NA entries; non-finite result is doubtful")
197+
## Is := diag( 1/sigma_i )
198+
pos <- !is.na(Is <- D <- diag(V, names=FALSE)) & D > 0
199+
Is[ pos] <- sqrt(1/D[pos])
200+
Is[!pos] <- NaN
201+
if(any(!pos) || any(!is.finite(Is)))
202+
warning("diag(V) had non-positive or NA entries; the non-finite result may be dubious")
200203
r <- V # keep dimnames
201204
r[] <- Is * V * rep(Is, each = p)
202205
## == D %*% V %*% D where D = diag(Is)

tests/reg-tests-1e.R

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1110,6 +1110,17 @@ stopifnot(identical(cov2cor(m00), m00))
11101110
## gave error in R <= 4.3.2
11111111

11121112

1113+
## cov2cor(.) warning(s) with negative/NA diag(.) - PR#18424
1114+
(D_1 <- diag(-1, 3L))
1115+
op <- options(warn=1)
1116+
m <- capture.output(r <- cov2cor(D_1), type = "message")
1117+
matrix(rep_len(c(1, rep(NaN,3)),3*3), 3) -> r0
1118+
stopifnot(all.equal(r, r0, tol = 0, check.attributes = FALSE),# always ok
1119+
length(m) == 2, grepl("^ *diag.V. ", m[2]))
1120+
options(op) # revert
1121+
## cov2cor() gave 2 warnings on 3 lines, the 2nd one inaccurate in R <= 4.3.2
1122+
1123+
11131124

11141125
## keep at end
11151126
rbind(last = proc.time() - .pt,

0 commit comments

Comments
 (0)