# Re: [R] diag() problem

From: Duncan Murdoch <murdoch_at_stats.uwo.ca>
Date: Sun 23 Oct 2005 - 03:37:59 EST

Duncan Murdoch wrote:

> On 10/19/2005 11:37 AM, Prof Brian Ripley wrote:
>

>>On Wed, 19 Oct 2005, Duncan Murdoch wrote:
>>
>>
>>>On 10/19/2005 10:55 AM, Robin Hankin wrote:
>>>
>>>>Hi
>>>>
>>>>I have a matrix "u", for which diag() gives an error:
>>>>
>>>>u <- structure(c(5.42334674128216, -2.31319389204264, -5.83059042218476,
>>>> -1.64112369640695, -2.31319389212801, 3.22737617646609,
>>>>1.85200668021569,
>>>> -0.57102273078531, -5.83059042231881, 1.85200668008156,
>>>>11.9488923894962,
>>>> -3.5525537165941, -1.64112369587405, -0.571022730886046,
>>>>-3.55255371755604,
>>>> 10.0989829379577), .Dim = c(4, 4), .Dimnames = list(c("constant",
>>>> NA, NA, NA), c("constant", NA, NA, NA)))
>>>>
>>>>
>>>>>u
>>>>
>>>> constant <NA> <NA> <NA>
>>>>constant 5.423347 -2.3131939 -5.830590 -1.6411237
>>>><NA> -2.313194 3.2273762 1.852007 -0.5710227
>>>><NA> -5.830590 1.8520067 11.948892 -3.5525537
>>>><NA> -1.641124 -0.5710227 -3.552554 10.0989829
>>>>
>>>>>is.matrix(u)
>>>>
>>>>[1] TRUE
>>>>
>>>>>diag(u)
>>>>
>>>>Error in if (is.list(nms) && !any(sapply(nms, is.null)) && all((nm <-
>>>>nms[[1]][1:m]) == :
>>>> missing value where TRUE/FALSE needed
>>>>
>>>>
>>>>
>>>>What's going on here?
>>>
>>>It's trying to check whether the row names match the column names, in
>>>which case it will assign those names to the diagonal elements. But the
>>>writer didn't figure someone would have NA names, so the test
>>>
>>>all((nm <- nms[[1]][1:m]) == nms[[2]][1:m])
>>>
>>>fails.
>>>
>>>It could be "fixed" by putting "na.rm=TRUE" into the all(), but that's
>>>probably not right:
>>>
>>>
>>>>all(c(1, NA) == c(1, 2), na.rm = TRUE)
>>>
>>>[1] TRUE
>>>
>>>I think we want to wrap the values in "paste", to convert to non-missing
>>>characters. That would be
>>>
>>>all(paste((nm <- nms[[1]][1:m])) == paste(nms[[2]][1:m]))
>>>
>>>and would give
>>>
>>>
>>>>diag(u)
>>>
>>> constant <NA> <NA> <NA>
>>> 5.423347 3.227376 11.948892 10.098983
>>>
>>>Any objections to me committing this change?
>>
>>Yes, you don't want <NA> to match "NA".
>>
>>If you think NA names should match, use identical. Otherwise (and I
>>think this would be more consistent with other parts of R), do something
>>like
>>
>>eq <- (nm <- nms[[1]][1:m]) == nms[[2]][1:m]
>>if(all(!is.na(eq) && eq)) ...
>>
>
>
> I agree with your objection; I realized the same thing just after I
> posted my original.  The solution I came up with was putting the all()
> in isTRUE().  I think that achieves an identical result to your solution.

I've just committed a fix for this to R-patched and R-devel. I didn't end up using isTRUE(all( ... )), instead I used Martin's suggested identical( ... ), since that's consistent with match(). This has the effect that Robin's example looks like this:

> diag(u)
constant <NA> <NA> <NA>   5.423347 3.227376 11.948892 10.098983

Duncan Murdoch

R-help@stat.math.ethz.ch mailing list