R 如何以规范的方式将as.list扩展到S4对象
我在将S4对象转换回列表时遇到一些问题。例如,以下嵌套的S4类:R 如何以规范的方式将as.list扩展到S4对象,r,s4,R,S4,我在将S4对象转换回列表时遇到一些问题。例如,以下嵌套的S4类: setClass("nssItem", representation(value = "numeric", text = "character", prefix = "character", type = "character"), prototype(value = as.numeric(NA), text = as.character(NA), prefix = as.character(
setClass("nssItem",
representation(value = "numeric", text = "character", prefix = "character", type = "character"),
prototype(value = as.numeric(NA), text = as.character(NA), prefix = as.character(NA), type = as.character(NA))
)
setClass("geckoNss", representation(absolute = "character", item = "nssItem"))
geckons
类的对象包含nssItem
类的对象。从概念上讲,这似乎是一个类似列表的结构,允许嵌套
然而
>临时组件列表(临时)
as.list.default(临时)中出错:
没有将此S4类强制为向量的方法
我理解这个错误,也就是说,我没有实际定义
as.list
的含义,也没有定义它如何应用于nssItem
类。尽管如此,这似乎是一个非常自然的操作。如何将as.list
的定义扩展到我定义的所有新类?我不确定是否正确理解了您关于“嵌套”的论点,但这里有一些关于如何将as.list
扩展到S4
类的代码。正如Alex在评论中指出的,这些实际上是S3
方法,用于S4
对象。这同样有效。你可以在这里找到关于这个主题的一个很好的摘要
现在,让我们在nssItem
对象temp
上尝试as.list
(定义见您的帖子)
编辑:我想我现在明白你说的嵌套是什么意思了。执行上述代码后,定义一个新的geckoNss
对象
tempGecko<-new("geckoNss")
as.list(tempGecko)
#$absolute
#character(0)
#
#$item
#$item$value
#[1] NA
#
#$item$text
#[1] NA
#
#$item$prefix
#[1] NA
#
#$item$type
#[1] NA
现在将as.list
应用到你的geckons
对象tempGecko
as.list(tempGecko)
#$absolute
#character(0)
#
#$item
#$item$value
#[1] NA
#
#$item$text
#[1] NA
#
#$item$prefix
#[1] NA
#
#$item$type
#[1] NA
根据下面的Alex评论,这里有一个扩展
As.list
的更通用的方法
#save old function definition (just in case...)
as.list.default.save=as.list.default
定义新的默认方法
as.list.default=function(x) {
if (class(x)=='list') {
x
} else if (class(x)%in%c('nssItem','geckoNss')) {
mapply(function(slot_name) as.list(slot(x,slot_name)),
slotNames(class(x)),
SIMPLIFY=FALSE)
} else {
.Internal(as.vector(x, "list"))
}
}
您仍然需要输入所有用户定义类的向量c('nssItem','geckons')
。我还没有找到返回这些类的函数。
结果的格式并不像上面那样好
as.list(temp)
#$value
#$value[[1]]
#[1] NA
#
#
#$text
#$text[[1]]
#[1] NA
#
#
#$prefix
#$prefix[[1]]
#[1] NA
#
#
#$type
#$type[[1]]
#[1] NA
这是第二个更普遍的解决方案。它使用从中派生所有用户定义类的超类。说明见
#
注释
#this is an "empty" superclass that characterises all user-defined classes
setClass("user_defined_class")
#we create an as.list method for this new superclass (this time an S4 method)
setMethod("as.list",signature(x="user_defined_class"),function(x) {
mapply(function(y) {
#apply as.list if the slot is again an user-defined object
#therefore, as.list gets applied recursively
if (inherits(slot(x,y),"user_defined_class")) {
as.list(slot(x,y))
} else {
#otherwise just return the slot
slot(x,y)
}
},
slotNames(class(x)),
SIMPLIFY=FALSE)
})
setClass("nssItem",
representation(value = "numeric",
text = "character",
prefix = "character",
type = "character"),
prototype(value = as.numeric(NA),
text = as.character(NA),
prefix = as.character(NA),
type = as.character(NA)),
#note the contains argument that flags the nssItem class as user-defined
contains="user_defined_class")
setClass("geckoNss",
representation(absolute = "character", item = "nssItem"),
#the same for the geckoNss class
contains="user_defined_class")
现在为每个类创建一个对象
temp <- new("nssItem")
tempGecko<-new("geckoNss")
以及tempGecko
对象
tempGecko<-new("geckoNss")
as.list(tempGecko)
#$absolute
#character(0)
#
#$item
#$item$value
#[1] NA
#
#$item$text
#[1] NA
#
#$item$prefix
#[1] NA
#
#$item$type
#[1] NA
谢谢你的回答。让我将
as.list
扩展到这两个对象,并将嵌套的s4对象转换为嵌套的列表,这非常有帮助。我认为同样的解包概念可以扩展到其他新类,但我不想为所有类编写asas.list
方法。这就是我在问题标题中所说的“canonical”。我还有一个问题,你能用as.list.
方法定义s4类上的新方法吗?我认为这是一种S3方式来定义method@Alex当R没有找到S4方法时,它使用S3方法(如果可用)。你也可以定义一个S4方法。很好,最新的编辑是把函数放到我想要的地方。我们是否能够使用rappy
来保留嵌套结构?我也对如何获得所有可用的类感兴趣:@Alex我想我现在找到了一个更好的解决方案。我会在一个单独的答案中发布它。这是一个非常漂亮的解决方案!但是,它依赖于项
表示为nssItem类
。这将是一个单独的问题,但我要求项
表示为nssItem
的对象列表。
temp <- new("nssItem")
tempGecko<-new("geckoNss")
as.list(temp)
#$value
#[1] NA
#
#$text
#[1] NA
#
#$prefix
#[1] NA
#
#$type
#[1] NA
as.list(tempGecko)
#$absolute
#character(0)
#
#$item
#$item$value
#[1] NA
#
#$item$text
#[1] NA
#
#$item$prefix
#[1] NA
#
#$item$type
#[1] NA