在R中向量化一个S4类

时间:2018-04-20 12:26:50

标签: arrays r class vector s4

我遇到了一些麻烦,它们以完全类型化的方式定义数组类(就R中的情况而言)。 我的例子:我想定义一个类Avector,它应该包含类A的任意数量的元素。

# Define the base class
setClass("A", representation(x = "numeric"))

# Some magic needed ????
setClass("Avector", ???)

# In the end one should be able to use it as follows:
a1 <- new("A", x = 1)
a2 <- new("A", x = 2)
X <- new("Avector", c(a1, a2))

我知道在R中不可能有一个对象向量。所以我猜它会被存储在一种&#34; typed&#34;名单。 我找到了一些解决方案,但我对此并不满意:

# Define the vectorized class
setClass(
  "Avector", 
  representation(X = "list"), 
  valididty = function(.Object)) {
    if (all(sapply(.Object@X, function(x) class(x) == "A")))
      TRUE
    else
      "'Avector' must be a list of elements in the class 'A'"
  }
)
# Define a method to subscript the elements inside of the vector
setMethod(
  "[", signature(x = "Avector", i = "ANY", j = "ANY"),
  function(x, i, j, ...) x@X[[i]]
)
# Test the class
a1 <- new("A", x = 1)
a2 <- new("A", x = 2)
avec <- new("Avector", X = list(a1, a2))
# Retrieve the element in index i
avec[i]

这种方法对我来说更像是黑客攻击。有没有办法在R中以规范的方式执行此操作而不用手工执行此类型检查和索引方法?

修改: 如果类A不是由原子槽组成,那么这也应该成立。例如,在以下情况下:

setClass("A", representation(x = "data.frame"))

我很乐意帮忙:) 干杯, 阿德里安

1 个答案:

答案 0 :(得分:1)

答案在某种程度上取决于您要完成的任务,并且在您的使用案例中可能会或可能不会。 S4的工作方式是对象应该是高级的,以避免过多的开销。

通常,插槽必须是矢量。您无法在R中定义新的原子类型。因此,在您的玩具示例中,而不是调用

avec <- new("Avector", X = list(a1, a2))
你打电话

avec <- new("A", x = c(1, 2))

例如,这可能需要其他插槽(以前是矢量)成为阵列。

如果您迫切希望拥有原子类型,那么您可以覆盖其中一种现有类型。我认为bit64包就是这样做的。基本上你要做的是创建一个继承自numeric的新类,然后编写许多方法来取代所有新类的默认方法。