我在以完全类型化的方式定义类似数组的类时遇到了一些麻烦(就 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 中不可能有一个对象向量。所以我猜它将存储在一种“类型化”列表中。 我找到了一些解决方案,但我对此不满意:
# 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]
这个方法对我来说更像是一种 hack。有没有办法在 R 中以规范的方式执行此操作,而无需手动执行此类型检查和索引方法?
编辑:
如果类 A
不由原子槽组成,这也应该成立。例如在以下情况:
setClass("A", representation(x = "data.frame"))
我很乐意提供帮助:) 干杯, 阿德里安
最佳答案
答案在某种程度上取决于您想要实现的目标,并且在您的用例中可能实现也可能不可能。 S4 的工作方式是对象应该是高层的,以避免过多的开销。
一般来说,槽必须是向量。您无法在 R 中定义新的原子类型。因此,在您的玩具示例中,不要调用
avec <- new("Avector", X = list(a1, a2))
你打电话
avec <- new("A", x = c(1, 2))
例如,这可能需要其他槽(以前是向量)变成数组。
如果您迫切需要原子类型,那么您也许可以覆盖现有类型之一。例如,我认为 bit64 包就是这样做的。本质上,您所做的就是创建一个继承自numeric
的新类,然后编写许多方法来取代新类的所有默认方法。
关于arrays - 在 R 中向量化 S4 类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49941636/