【问题标题】:How to distinguish M[2, ] from M[2]?如何区分M[2, ]和M[2]?
【发布时间】:2023-01-20 16:35:31
【问题描述】:

我定义了一些S4矩阵,它的类是lazyMatrix。如果M是这样的矩阵,我想将M[2, ]定义为M的第二行,将M[2]定义为M的第二个系数(当逐列枚举系数时)。

所以我定义了这两个 S4 方法:

setMethod( # to extract a coefficient
  "[", 
  signature("lazyMatrix", i = "numeric"), 
  function(x, i) {
    ......
  }
)

setMethod( # to extract a row
  "[", 
  signature("lazyMatrix", i = "numeric", j = "missing", drop = "ANY"), 
  function(x, i, j, drop) {
    ......
  }
)

但是M[2, ]M[2] 都返回M 的第二行。我试图交换两个方法定义的顺序,但没有任何改变。

【问题讨论】:

标签: r s4


【解决方案1】:

我在源代码中找到了解决方案洋葱包裹:

setMethod(
  "[", 
  signature("lazyMatrix", i = "numeric", j = "missing", drop = "missing"), 
  function(x, i, j, ..., drop) {
    n_args <- nargs()
    if(n_args == 3L) { # M[i, ]
      ......  
    } else if(n_args == 2L) { # M[i]
      ......
    } else {
      stop("Invalid arguments in subsetting.")
    }
  }
)

setMethod(
  "[", 
  signature("lazyMatrix", i = "numeric", j = "missing", drop = "ANY"), 
  function(x, i, j, ..., drop) {
    n_args <- nargs()
    if(n_args == 4L) { # M[i, ]
      ......  
    } else if(n_args == 3L) { # M[i]
      ......
    } else {
      stop("Invalid arguments in subsetting.")
    }
  }
)

在找到此解决方案之前,我尝试使用 nargs() 进行尝试,但未成功。诀窍是添加 ... 参数。但我不明白这是怎么回事。如果您可以解释,请留下另一个答案或评论。

【讨论】:

  • 想知道在没有插入 ... 的情况下,“drop”是否被解释为另一个参数,如“i”和“j”,而不是被解释为所需的?只是一个猜测
【解决方案2】:

调度问题与点无关,尽管它问题在于您的方法的形式参数与通用函数的形式参数不匹配:

> getGeneric("[")
standardGeneric for "[" defined from package "base"

function (x, i, j, ..., drop = TRUE) 
standardGeneric("[", .Primitive("["))
<bytecode: 0x1403d1a28>
<environment: 0x1403c9d10>
Methods may be defined for arguments: x, i, j, drop
Use  showMethods([)  for currently available ones.

?setMethod 对此很清楚:

定义必须是一个函数,其形式参数与泛型相同;但是,setMethod() 将处理添加参数的方法,如果 ... 是泛型的正式参数。请参阅详细信息部分。

不管怎样,真正的问题是setMethod解释了你的第一个签名

signature("lazyMatrix", i = "numeric")

作为

signature("lazyMatrix", i = "numeric", j = "ANY", drop = "ANY")

M[2]M[2, ] 这两个电话都匹配您的第二个签名

signature("lazyMatrix", i = "numeric", j = "missing", drop = "ANY")

比第一个更接近(因为"missing""ANY"更具体)。因此,在这两种情况下,调度都倾向于第二种方法。

由于传统矩阵(隐式类matrix)的 C 代码中处理的所有特殊情况,原始函数 [ 仍然是最棘手的泛型函数。 nargs() 方法是正确的,Matrix 包也使用了它,这确实是此类事情的规范参考:

> library(Matrix)
> selectMethod("[", signature = c("Matrix", "numeric", "missing", "missing"))
Method Definition:

function (x, i, j, ..., drop = TRUE) 
{
    Matrix.msg("M[i,m,m] : nargs()=", nargs(), .M.level = 2)
    if (nargs() == 2) {
        .M.vectorSub(x, i)
    }
    else {
        callGeneric(x, i = i, , drop = TRUE)
    }
}
<bytecode: 0x128e94a90>
<environment: namespace:Matrix>

Signatures:
        x        i         j         drop     
target  "Matrix" "numeric" "missing" "missing"
defined "Matrix" "index"   "missing" "missing"

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-04-11
    • 1970-01-01
    • 2013-09-24
    • 2011-12-06
    • 1970-01-01
    • 2018-11-15
    • 1970-01-01
    相关资源
    最近更新 更多