Skip to content

Instantly share code, notes, and snippets.

@ClaytonJY
Last active January 3, 2018 20:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ClaytonJY/f663a9462a29669f79faad6d2eeaec6c to your computer and use it in GitHub Desktop.
Save ClaytonJY/f663a9462a29669f79faad6d2eeaec6c to your computer and use it in GitHub Desktop.
R's diag function does weird things
diag(1.1)          
#>      [,1]
#> [1,]    1
diag(0.9)          
#> <0 x 0 matrix>
diag(0.9, nrow = 1)
#>      [,1]
#> [1,]  0.9
diag(-1)           
#> Error in diag(-1): invalid 'nrow' value (< 0)
# oh, it's treating this as the nrow arg?
diag(x = -1)       
#> Error in diag(x = -1): invalid 'nrow' value (< 0)
# ugh
diag(-1, nrow = 1) 
#>      [,1]
#> [1,]   -1
@dankessler
Copy link

dankessler commented Jan 2, 2018

Usage

diag(x = 1, nrow, ncol)
diag(x) <- value

So, equivalently:

> diag(x=1,nrow=1.1)
     [,1]
[1,]    1
> diag(x=1,nrow=0.9)
<0 x 0 matrix>
> diag(x=0.9,nrow=1)
     [,1]
[1,]  0.9

This seems like a consequence of the first argument having a default value while the latter two do not have a default value. The third example seems to illustrate the weird stuff that can happen when mixing positional and named arguments and how this can interact with specifying default values for earlier parameters but not later parameters.

@dankessler
Copy link

dankessler commented Jan 3, 2018

Useful update. If you include some bigger values, e.g. diag(6), it's especially clear that it interprets it as nrow

@ellisvalentiner
Copy link

The problem is that diag tries to do too many things:

 ‘diag’ has four distinct usages:

   1. ‘x’ is a matrix, when it extracts the diagonal.

   2. ‘x’ is missing and ‘nrow’ is specified, it returns an
      identity matrix.

   3. ‘x’ is a scalar (length-one vector) and the only argument, it
      returns a square identity matrix of size given by the scalar.

   4. ‘x’ is a ‘numeric’ (‘complex’, ‘numeric’, ‘integer’,
      ‘logical’, or ‘raw’) vector, either of length at least 2 or
      there were further arguments.  This returns a matrix with the
      given diagonal and zero off-diagonal entries.

 It is an error to specify ‘nrow’ or ‘ncol’ in the first case.

compare to a language like Julia where there are separate functions for separate uses

function use
diag(M, k::Integer=0) The kth diagonal of a matrix, as a vector.
diagm(v, k::Integer=0) Construct a matrix by placing v on the kth diagonal.
Diagonal(A::AbstractMatrix) Constructs a matrix from the diagonal of A.

So when you use diag(-1) or diag(0.9) in R what do you expect?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment