Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/69.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中创建用户定义的S4类的数据帧_R_S4 - Fatal编程技术网

如何在R中创建用户定义的S4类的数据帧

如何在R中创建用户定义的S4类的数据帧,r,s4,R,S4,我想创建不同变量的data.frame,包括S4类。对于像“POSIXlt”(用于日期)这样的内置类,这很好: as.data.frame(list(id=c(1,2), date=c(as.POSIXlt('2013-01-01'),as.POSIXlt('2013-01-02')) 但现在我有了一个用户定义的类,比如一个带有姓名和年龄的“Person”类: setClass("person", representation(name="charact

我想创建不同变量的data.frame,包括S4类。对于像“POSIXlt”(用于日期)这样的内置类,这很好:

as.data.frame(list(id=c(1,2), 
                   date=c(as.POSIXlt('2013-01-01'),as.POSIXlt('2013-01-02'))
但现在我有了一个用户定义的类,比如一个带有姓名和年龄的“Person”类:

setClass("person", representation(name="character", age="numeric"))
但以下几点失败了:

as.data.frame(list(id=c(1,2), pers=c(new("person", name="John", age=20),
                                     new("person", name="Tom", age=30))))
as.data.frame(list(id=c(1,2), pers=persons))
我还尝试使用重载person类的[…]操作符

setMethod(
  f = "[",
  signature="person",
  definition=function(x,i,j,...,drop=TRUE){ 
    initialize(x, name=x@name[i], age = x@age[i])
  }
)
这允许类似向量的行为:

persons = new("person", name=c("John","Tom"), age=c(20,30))
p1 = persons[1]
但以下几点仍然失败:

as.data.frame(list(id=c(1,2), pers=c(new("person", name="John", age=20),
                                     new("person", name="Tom", age=30))))
as.data.frame(list(id=c(1,2), pers=persons))
也许我必须重载更多的运算符才能将用户定义的类放入数据帧中?我相信,一定有办法做到这一点,因为POSIXlt是一个S4类,它可以工作!任何使用新的R5引用类的解决方案都可以

我不想把我所有的数据都放到person类中(你可以问,为什么“id”不是person的成员,我只是不使用dataframes)!其思想是,my data.frame表示数据库中的一个表,该表包含许多不同类型的列,例如字符串、数字等,。。。还有日期、间隔、地理对象等。。。对于日期,我已经有了一个解决方案(POSIXlt),对于间隔、地理对象等,我可能需要指定自己的S4/R5类


提前非常感谢。

从邮件列表上的这条线索判断:

…约翰·钱伯斯在2006年考虑过这个问题。我们仍然不能将S4对象放在数据帧的列中。我们也不能将复杂的S3类放在数据帧列中

可能还有其他一些表格数据结构可以做到这一点-data.table:

require(data.table)
setClass("geezer", representation(name="character", age="numeric"))
tom=new("geezer",name="Tom",age=20)
dick=new("geezer",name="Dick",age=23)
harry=new("geezer",name="Harry",age=25)
gt = data.table(geezers=c(tom,dick,harry),weapons=c("Gun","Gun","Knife"))
gt
    geezers weapons
1: <geezer>     Gun
2: <geezer>     Gun
3: <geezer>   Knife
require(data.table)
setClass(“geezer”,表示法(name=“character”,age=“numeric”))
汤姆=新的(“geezer”,name=“汤姆”,年龄=20岁)
迪克=新的(“geezer”,name=“迪克”,年龄=23岁)
harry=新(“geezer”,name=“harry”,年龄=25岁)
gt=数据表(geezers=c(汤姆、迪克、哈利),武器=c(“枪”、“枪”、“刀”))
燃气轮机
极客武器
1:枪
2:枪
3:刀
data.table的语义与data.frame有点不同,不要期望能够将data.table插入使用data.frame的任何代码中,并期望它工作(例如,我怀疑
lm
glm
将不稳定)。但是data.table的作者似乎允许在列中使用复合类…

这是您的类,它的定义是“列”解释,而不是行;这对绩效非常重要;另附日期供参考

setClass("person", representation(name="character", age="numeric"))
pers <- new("person", name=c("John", "Tom"), age=c(20, 30))
date <- as.POSIXct(c('2013-01-01', '2013-01-02'))
这将获取data.frame中的对象:

> lst <- list(id=1:2, date=date, pers=pers)
> as.data.frame(lst)
     id       date     pers
John  1 2013-01-01 John, 20
Tom   2 2013-01-02  Tom, 30
我不确定当遇到更多的
data.frame
操作时,可能需要什么其他方法,因为没有“data.frame接口”

在data.table中使用矢量化类似乎需要一个长度方法来构造

> library(data.table)
> data.table(id=1:2, pers=pers)
Error in data.table(id = 1:2, pers = pers) : 
  problem recycling column 2, try a simpler type
> setMethod(length, "person", function(x) length(x@name))
[1] "length"
> data.table(id=1:2, pers=pers)
   id     pers
1:  1 John, 20
2:  2  Tom, 30

可能有data.table接口?

POSIXlt对象是S3类,而不是S4类<代码>p=as.POSIXlt('2013-01-01');isS4(p)返回FALSE。您是对的。另外,“person”已经是一个R类。使用S3类,我没有得到错误,即
p=structure(list(name=“Tom”,age=20),class=“mypers”);as.data.frame(list(id=c(1,2),pers=c(p,p))
运行。但我得到的结果是5列(而不是2列;一列表示id,一列表示pers)。仍然不能解决这个问题。无论如何谢谢你+1
lm
glm
不会摇晃<代码>数据。表与它们完全兼容。他们幸福地不知道
数据表。解释它是如何工作的。我们根本没有意识到与任何其他包的任何不兼容。他们在
data.table
上使用传统的
[.data.frame
语法,而且很有效。我知道人们经常说基本上是兼容的,但我们不知道有什么不兼容的地方。FAQ 2.17的最后一段提到了这一点。但它确实应该在
?data.table
中突出(将添加).只要我不尝试从数据表中拟合一个包含复合S4类的模型?这可能是一件奇怪的事情,但有人可能会期望这些对象像一个因子一样工作……没错,也许不是。实际上,那一段中有错别字:应该“使用
数据。表
”应该“使用
数据。框架
”?但是,是的,对象作为单元格值是一个预期功能,尽管可能没有简单的东西测试得那么好。非常感谢您使用data.table!我只是梦想有一个包,可以通过JDBC将数据库表导入到R中,其中包含所有JDBC对象(包括间隔、地理对象等)给定的列中有一个以适当的S4/R5类表示。有一个RJDBC包,它已经提供了一种使用R和JDBC查询数据库的智能方法…但不幸的是,所有内容都转换为字符和数字…这样的data.table可以提供更多!非常感谢您提出的重载as.data.frame.CLAS的想法在你的想法的帮助下,我甚至设法让它运行我的原始代码——我使用
c.person=function(…){args=list(…);return(new)(“personx”,name=sapply(args,function(x))重载了c方法x@name),年龄=sapply(参数,函数(x)x@age)))}
然后是
c(p1,p2)的结果
其中p1、p2是人,可以包含在数据帧中。恐怕我不太使用S4,所以我有点迷路了。@SteveLianoglou是data.table项目的合著者,比我更了解S4。@MatthewDowle这不是S4的问题;S3类需要实现哪些方法才能与data.table兼容,例如,
pers=structrue(list(name=c(“Tom”、“Bob”)、age=c(20,30)、sex=c(“M”、“M”)、class=“s3person”)
可能具有
length.s3person=function(x)length(x$name)
,即包含的向量的长度,而不是包含类的列表的长度。
数据表需要哪些方法(id=1:2,pers=pers)
,等等,工作吗?哦,我明白了。只需将
pers
包装在
list()
中,例如
数据。表(id=1:2,pers=list(pers))
工作,然后它会回收对象,并在单元格值
中打印类名。