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.
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.
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.
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.
We can use the length() function combined with double brackets to count the number of elements in a specific component of the list.
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 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:
.
> 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:
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With