当编写使用Matrix包的R包时,为什么我必须指定Matrix :: t()而不是仅指定t()? [英] When writing an R package that uses the Matrix package, why do I have to specify Matrix::t() instead of just t()?
问题描述
考虑以下在R会话中定义的简单函数:
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
如果我们将这些相同的函数放入包中,则transpose.a.Matrix
函数将不再起作用. 由于描述程序包创建过程太长,因此我只发布了程序包的副本
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>
我认为这里的关键是关于名称空间的怪异之处.请注意,如果我调试该函数,则可以手动调用Matrix::t
,当base::t
失败并出现相同错误时,它将起作用.
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
但是使用showMethods
时,它建议仅使用t
应该找到正确的,即使没有.
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"
现在,我可以通过编辑包的源代码来修复"它,以便transpose.a.Matrix
函数指定它需要Matrix::t
方法:
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?
我的DESCRIPTION文件是
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'
我的NAMESPACE文件是
My NAMESPACE file is
export(make.a.Matrix)
export(transpose.a.Matrix)
,我可以应要求发布其他作品.
and I can post additional pieces upon request.
推荐答案
关于gitHub的工作示例
我在gitHub上放置了一个工作示例,以便轻松浏览不同文件.
仅供参考,由于它是使用devtools
构建的,因此它并不是一个最小的示例. 附加"是(1)roxygen2
注释是构建NAMESPACE文件的基础,以及(2)它结合了testthat
的单元测试.在本示例中,所有这些都可以忽略.
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.
事实上,我所做的简短回答需要将我的NAMESPACE文件更改为:
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)
以便R可以找到正确的转置版本.有关R如何搜索的详细说明,请参见此帖子功能.
So that R could find the right version of transpose. See this post for a great description of how R searches for functions.
尽管并非绝对必要,但我将我的DESCRIPTION文件修改为一点点清洁器:
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'
请注意,我将Depends:
用于Matrix
而不是Imports:
,以便用户将能够使用函数返回的Matrix
对象.如果此示例仅在内部使用Matrix
东西而不向用户展示,则我将使用Imports:
.
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
请注意,如果我在Imports:
中而不是Depends:
中指定了Matrix
,则最后一条命令将失败.
Note that the last command would have failed if I had specified Matrix
in Imports:
and not Depends:
.
这篇关于当编写使用Matrix包的R包时,为什么我必须指定Matrix :: t()而不是仅指定t()?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!