问题
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 <nathanvan@letterafterFmail.com>
Maintainer: Nathan VanHoudnos <nathanvan@letterafterFmail.com>
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.
回答1:
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 <nathanvan@letterafterFmail.com>
Maintainer: Nathan VanHoudnos <nathanvan@letterafterFmail.com>
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:
.
来源:https://stackoverflow.com/questions/17580935/when-writing-an-r-package-that-uses-the-matrix-package-why-do-i-have-to-specify