Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When writing an R package that uses the Matrix package, why do I have to specify Matrix::t() instead of just t()?

Consider the following simple functions defined in an R session:

nathanvan@nathanvan-N61Jq:~$ R

R version 3.0.1 (2013-05-16) -- "Good Sport"
... snip ... 
> make.a.Matrix <- function(data, nrow, ncol) {
+    require(Matrix)
+    return( Matrix(data, nrow=nrow, ncol=ncol))
+ }
> 
> transpose.a.Matrix <- function(data, nrow, ncol  ) {
+   return(t( make.a.Matrix(data, nrow=nrow, ncol=ncol) ))
+ }
> 
> make.a.Matrix(1:12, 3, 4)
Loading required package: Matrix
Loading required package: lattice
3 x 4 Matrix of class "dgeMatrix"
     [,1] [,2] [,3] [,4]
[1,]    1    4    7   10
[2,]    2    5    8   11
[3,]    3    6    9   12
> transpose.a.Matrix(1:12, 3, 4)
4 x 3 Matrix of class "dgeMatrix"
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    4    5    6
[3,]    7    8    9
[4,]   10   11   12

If we put those same functions into a package, the transpose.a.Matrix function no longer works. Since describing the package creation process would be too lengthy, I have simply posted a copy of the package here. I have posted the DESCRIPTION and NAMESPACE files at the end of the question. If other pieces are relevant, I'd be happy to post them too. Just let me know!

nathanvan@nathanvan-N61Jq:~$ R

R version 3.0.1 (2013-05-16) -- "Good Sport"
... snip ... 
> require(minimalbugexample)
Loading required package: minimalbugexample
Loading required package: Matrix
Loading required package: lattice
Loading required package: testthat
> make.a.Matrix(1:12, 3, 4)
3 x 4 Matrix of class "dgeMatrix"
     [,1] [,2] [,3] [,4]
[1,]    1    4    7   10
[2,]    2    5    8   11
[3,]    3    6    9   12
> transpose.a.Matrix(1:12, 3, 4)
Error in t.default(make.a.Matrix(data, nrow = nrow, ncol = ncol)) : 
  argument is not a matrix
> transpose.a.Matrix
function(data, nrow, ncol  ) {
  return(t( make.a.Matrix(data, nrow=nrow, ncol=ncol) ))
}
<environment: namespace:minimalbugexample>

I think that the key here is something weird about the namespace. Notice that if I debug the function, I can manually call the Matrix::t and it will work while the base::t fails with the same error.

> debug(transpose.a.Matrix)
> transpose.a.Matrix(1:12, 3, 4)
debugging in: transpose.a.Matrix(1:12, 3, 4)
debug at /home/nathanvan/Ubuntu One/workspace/experimental-design/software/minimalbugexample/R/use-Matrix-package.R#31: {
    return(t(make.a.Matrix(data, nrow = nrow, ncol = ncol)))
}
Browse[2]> t(Matrix(1:12, 3, 4))
Error in t.default(Matrix(1:12, 3, 4)) : argument is not a matrix
Browse[2]> t
function (x) 
UseMethod("t")
<bytecode: 0x46b0a88>
<environment: namespace:base>
Browse[2]> Matrix::t(Matrix(1:12, 3, 4))
4 x 3 Matrix of class "dgeMatrix"
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    4    5    6
[3,]    7    8    9
[4,]   10   11   12
Browse[2]> base::t(Matrix(1:12, 3, 4))
Error in t.default(Matrix(1:12, 3, 4)) : argument is not a matrix

And yet using showMethods, it suggest that just using t should find the right one, even though it did not.

Browse[2]> showMethods('t')
Function: t (package base)
x="ANY"
x="CsparseMatrix"
x="dgeMatrix"
x="diagonalMatrix"
x="dppMatrix"
x="dsCMatrix"
x="dspMatrix"
x="dsTMatrix"
x="dsyMatrix"
x="dtpMatrix"
x="dtrMatrix"
x="dtTMatrix"
x="lgeMatrix"
x="lspMatrix"
x="lsTMatrix"
x="lsyMatrix"
x="ltpMatrix"
x="ltrMatrix"
x="ltTMatrix"
x="matrix"
    (inherited from: x="ANY")
x="Matrix"
x="ngeMatrix"
x="nspMatrix"
x="nsTMatrix"
x="nsyMatrix"
x="ntpMatrix"
x="ntrMatrix"
x="ntTMatrix"
x="pMatrix"
x="RsparseMatrix"
x="TsparseMatrix"

For now, I can “fix” it by editing the source for the package so that the transpose.a.Matrix function specifies that it needs the Matrix::t method:

transpose.a.Matrix <- function(data, nrow, ncol  ) {
  require(Matrix)
  return(Matrix::t( make.a.Matrix(data, nrow=nrow, ncol=ncol) ))
}

But that seems like it should not be needed. What am I missing?

My DESCRIPTION file is

Package: minimalbugexample
Title: 
Description: 
Version: 0.1
Author: Nathan VanHoudnos <[email protected]>
Maintainer: Nathan VanHoudnos <[email protected]>
Depends:
    R (>= 3.0.1),
    Matrix (>= 1.0),
    testthat
License: GPL
LazyData: true
Collate:
    'minimalbugexample-package.r'
    'use-Matrix-package.R'

My NAMESPACE file is

export(make.a.Matrix)
export(transpose.a.Matrix)

and I can post additional pieces upon request.

like image 849
Nathan VanHoudnos Avatar asked Jul 10 '13 21:07

Nathan VanHoudnos


People also ask

What is matrix package in R?

The Matrix package contains functions that extend R to support highly dense or sparse matrices. It provides efficient access to BLAS (Basic Linear Algebra Subroutines), Lapack (dense matrix), TAUCS (sparse matrix) and UMFPACK (sparse matrix) routines.

How do you transpose a matrix in R?

Rotating or transposing R objects frame so that the rows become the columns and the columns become the rows. That is, you transpose the rows and columns. You simply use the t() command. The result of the t() command is always a matrix object.

What is a sparse matrix R?

A sparse matrix is a type of matrix that has most of the elements equal to zero but there is no restriction for the number of zero elements. As a general criterion the number of non−zero elements are expected to be equal to the number of rows or number of columns.

How do you count elements in a matrix in R?

We can use the length() function combined with double brackets to count the number of elements in a specific component of the list.


1 Answers

A working example on gitHub

I put a working example on gitHub so that it is easy to browse the different files.

FYI, it's not quite a minimal example since it was built with devtools. The "extras" are (1) that roxygen2 comments are what builds the NAMESPACE file, and (2) it incorporates unit testing with testthat. All of that can be ignored for the purposes of this example.

The key fix

The short answer that I did, in fact, need to change my NAMESPACE file to:

export(make.a.Matrix)
export(transpose.a.Matrix)
importFrom(Matrix,Matrix)
importFrom(Matrix,t)

So that R could find the right version of transpose. See this post for a great description of how R searches for functions.

Although not strictly necessary, I modified my DESCRIPTION file to be a tad bit cleaner:

Package: minimalbugexample
Title: 
Description: 
Version: 0.1.3
Author: Nathan VanHoudnos <[email protected]>
Maintainer: Nathan VanHoudnos <[email protected]>
Depends:
    R (>= 3.0.1),
    Matrix (>= 1.0)
Suggests:
    testthat (>= 0.7.1.99)
License: GPL
LazyData: true
Collate:
    'minimalbugexample-package.r'
    'use-Matrix-package.R'

Note that I am using Depends: for Matrix instead of Imports: so that the user will be able to use the Matrix objects that the functions return. If this example only used the Matrix stuff internally without presenting it to the user, I'd have used Imports:.

Proof that it works

> require(minimalbugexample)
> make.a.Matrix(1:12, 3, 4)
3 x 4 Matrix of class "dgeMatrix"
     [,1] [,2] [,3] [,4]
[1,]    1    4    7   10
[2,]    2    5    8   11
[3,]    3    6    9   12
> transpose.a.Matrix(1:12, 3, 4)
4 x 3 Matrix of class "dgeMatrix"
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    4    5    6
[3,]    7    8    9
[4,]   10   11   12
> t( make.a.Matrix(1:12, 3, 4))
4 x 3 Matrix of class "dgeMatrix"
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    4    5    6
[3,]    7    8    9
[4,]   10   11   12

Note that the last command would have failed if I had specified Matrix in Imports: and not Depends:.

like image 183
Nathan VanHoudnos Avatar answered Oct 15 '22 21:10

Nathan VanHoudnos