【问题标题】:R S4 overloading of subscript operator for base matrix classR S4基矩阵类的下标运算符重载
【发布时间】:2014-03-13 12:07:18
【问题描述】:

我以这种方式定义了一个名为 FilterCommandIndices 的 S4 类:

setClass('FilterCommandIndices',
     representation(rows='logical', cols='logical')
     )

它只包含两个槽,逻辑向量指示给定的行或列是否包含在集合中。然后我想重载下标运算符以使其与上一个类一起使用。我最初的实现是这样的:

setMethod('[', c(x='ANY', i='FilterCommandIndices', j='missing'),
      function(x, i, j, ..., drop=TRUE) {
        if (nrow(x) != length(getRows(i)) || ncol(x) != length(getCols(i))) {
          stop('Incorrect number of dimensions')
        } else {
          return(x[getRows(i), getCols(i)])
        }
      })

在前面的代码中,getRows() 和 getCols() 是 FilterCommandIndices 类对应的普通访问器:

setGeneric('getRows', function(object) standardGeneric('getRows'))

setMethod('getRows', 'FilterCommandIndices',
      function(object) {
        return(object@rows)
      })

setGeneric('getCols', function(object) standardGeneric('getCols'))

setMethod('getCols', 'FilterCommandIndices',
      function(object) {
        return(object@cols)
      })

我认为通过使用 ANY 签名,我可以使这个简单的类和运算符组合即使在基类中也能工作,就像一个简单的 matrix。虽然它似乎适用于示例类...

d> bar1
An object of class "FilterCommandIndices"
Slot "rows":
[1] FALSE  TRUE  TRUE  TRUE  TRUE

Slot "cols":
[1] TRUE TRUE TRUE TRUE TRUE

d> mockMethylSet
MethylSet (storageMode: lockedEnvironment)
assayData: 5 features, 5 samples 
  element names: Meth, Unmeth 
phenoData: none
Annotation
Preprocessing
  Method: unknown
  minfi version: unknown
  Manifest version: unknown

d> mockMethylSet[bar1]
MethylSet (storageMode: lockedEnvironment)
assayData: 4 features, 5 samples 
  element names: Meth, Unmeth 
phenoData: none
Annotation
Preprocessing
   Method: unknown
  minfi version: unknown
  Manifest version: unknown

...但不在基础 matrix 类中:

d> zeroDetectionP
   S1 S2 S3 S4 S5
F1  0  0  0  0  0
F2  0  0  0  0  0
F3  0  0  0  0  0
F4  0  0  0  0  0
F5  0  0  0  0  0

d> zeroDetectionP[bar1]
Error en zeroDetectionP[bar1] : invalid subscript type 'S4'

setMethod 文档中,它说您可以使用签名中的基类定义方法,这让我认为我可以使用 ANY em> 签名并仅在下标对象未实现 nrow()、ncol() 或运算符 '[' 时失败。

任何帮助或提示将不胜感激。

更新:设置特定的签名方法(如@hadley 建议的那样)

如果我为矩阵基类设置具有特定签名的方法...

d> getMethod('[', c(x='matrix', i='FilterCommandIndices', j='missing'))
Method Definition:

function (x, i, j, ..., drop = TRUE) 
{
    return(x) # Dummy method
}

...然后再次尝试下标矩阵...

d> zeroDetectionP[bar1]
Error en zeroDetectionP[bar1] : invalid subscript type 'S4'

...错误仍然存​​在。

更新:最小可重现示例

我尝试编写一个最小的场景来重现之前的场景。我认为,这是一个给出相同错误的简单场景。正如@hadley 所建议的那样,这可能是由于下标是一个原语。

library(methods)

setClass('Indices', representation(rows='logical', cols='logical'))

setMethod('[', c(x='ANY', i='Indices', j='missing'),
      function(x, i, j, ..., drop=FALSE) {
        return(x[i@rows, i@cols])
      })

setClass('M', representation(m='matrix'))

setMethod('[', c(x='M', i='logical', j='logical'),
      function(x, i, j, ..., drop=FALSE) {
        return(x@m[i, j])
      })

anIndicesObject <- new('Indices', rows=c(TRUE, TRUE, FALSE), cols=c(FALSE, TRUE, FALSE))
aMatrix <- matrix(1:9, nrow=3)
aMobject <- new('M', m=aMatrix)

aMobject # Prints the M object
aMobject[c(TRUE, TRUE, FALSE), c(TRUE, TRUE, TRUE)] # Susbcript by logical vector
aMobject[anIndicesObject] # Subscript by Indices class
aMatrix[anIndicesObject] # Subscript a matrix by Indices --> ERROR

【问题讨论】:

  • 尝试明确的setMethod('[', c(x='matrix', i='FilterCommandIndices', j='missing') ?
  • 我已经有了。编辑问题以添加额外信息。
  • 嗯,可能是因为 [ 是原始的。但是,如果您制作一个 minimal 可重现的示例,该示例可以轻松复制并粘贴到 R 中,您更有可能获得帮助。
  • 对不起,我以为场景很简单。我已经编辑了这个问题,以提供我认为是一个最小的例子。感谢您的建议。

标签: r operator-overloading s4


【解决方案1】:

更小的可重现示例:

library(methods)

setClass("Indices", representation(rows = "logical", cols = "logical"))
x <- new("Indices", rows=c(TRUE, TRUE, FALSE), cols=c(FALSE, TRUE, FALSE))
m <- matrix(1:9, nrow=3)
m[x]

# Method doesn't appear to be found for signature x = "ANY"
show_s4 <- function(x, i, j, ..., drop=FALSE) "S4"
setMethod("[", signature(x = "ANY", i = "Indices", j = "missing"), show_s4)
m[x]

# Or even with explicit "matrix" in signature
setMethod("[", signature(x = "matrix", i = "Indices"), show_s4)
m[x]
# Error in m[x] : invalid subscript type "S4"

# Describing all arguments also fails
getGeneric("[")
setMethod(
  "[", 
  signature(x = "matrix", i = "Indices", j = "missing", drop = "missing"),
  show_s4
)
m[x]

我认为关键是?Methods中的这句话:

如果使用 S3 泛型函数,则不会单独看到 S4 方法 被直接调用。但是,原始函数和运算符 例外情况:内部 C 代码将查找 S4 方法,如果并且 仅当对象是 S4 对象时。

由于矩阵不是 S4 类,您不能在内部泛型方法中调度它(如 [

【讨论】:

  • 太棒了!非常感谢!现在它是有道理的,至少我可以从 ?Methods 中的那句话中得到所有的意义。感谢您的宝贵时间。
猜你喜欢
  • 2012-05-04
  • 1970-01-01
  • 1970-01-01
  • 2015-07-29
  • 1970-01-01
  • 1970-01-01
  • 2016-02-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多