Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R 如何以规范的方式将as.list扩展到S4对象_R_S4 - Fatal编程技术网

R 如何以规范的方式将as.list扩展到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(

我在将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(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对象转换为嵌套的列表,这非常有帮助。我认为同样的解包概念可以扩展到其他新类,但我不想为所有类编写as
as.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