Trying to build a new class on the base of an 'ordered' class, using R.version 3.3.1 tried also on new R-devel
R Under development (unstable) (2016-10-26 r71594) -- "Unsuffered Consequences"
I get an error:
> setClass('newFactor', representation = c(tempValue = 'character'), contains = c('ordered'))
Error in validObject(.Object) :
invalid class “classRepresentation” object: invalid object for slot "slots" in class "classRepresentation": got class "character", should be or extend class "list"
>
The same thing works on the stable Version 3.2.5
EDIT
OK thanks #hrbrmstr I understood that R 3.3 does not support using S3 objects inside S4 objects but I am still puzzled. This:
numWithId <- setClass("numWithId", slots = c(id = "character"),contains = "numeric")
should work but this :
numWithId <- setClass("numWithId", slots = c(id = "character"),contains = "factor")
should not, except it does!
> numWithId <- setClass("numWithId", slots = c(id = "character"),contains = 'factor')
> new('numWithId')
An object of class "numWithId"
integer(0)
Slot "id":
character(0)
Slot "levels":
character(0)
Slot ".S3Class":
[1] "factor"
On the other hand this does not work:
numWithId <- setClass("numWithId", slots = c(id = "character"),contains = 'ordered')
Error in makePrototypeFromClassDef(properties, ClassDef, immediate, where) :
in constructing the prototype for class “numWithId”: prototype has class “S4”, but the data part specifies class “integer”
When I add list to the contains = it works {I have a feeling that this is not the right way of doing this}
> setClass("numWithId", slots = c(id = "character"),contains = c('list', 'ordered'))
> new("numWithId")
An object of class "numWithId"
list()
Slot "id":
character(0)
Slot ".S3Class":
[1] "ordered" "factor"
Slot "levels":
character(0)
>
What is the right way of inheriting an S3 object in to an S4 object?
Related
My aim is to define one of the slots of class Security as another class Quote.
First I define class Quote:
Quote <- setClass("Quote", slots = c(Last = "numeric", Settle = "numeric"))
Then I am trying to define class Security as following:
Security <- setClass("Security", slots = c(Name = "character", Price = "Quote"))
Finally I am trying to create constructor for class Security:
Security <- function(Name = character(), Last = numeric(), Settle = numeric())
new("Security", Name = Name, Price#Last = Last, Price#Settle = Settle)
Unfortunately, this code doesn't work...
Thanks in advance.
If offering the user a constructor named Security, make sure the default constructor is named differently
.Security <- setClass("Security", slots = c(Name = "character", Price = "Quote"))
In your own constructor, create the slot instance as an argument to default constructor; use ... to allow for class inheritance
Security <-
function(Name = character(), Last = numeric(), Settle = numeric(), ...)
{
.Security(Name=Name, Price=Quote(Last=Last, Settle=Settle), ...)
}
I'm still trying to learn S4, and I see that a recognized expert has already given an answer, so I'm mostly posting this as an example for critique:
.Quote <- setClass("Quote", slots = c(Last = "numeric", Settle = "numeric"))
.Security <- setClass("Security", slots = c(Name = "character", Price = "Quote"))
aNewSecurity <- .Security(Name = "newSec",
Price = .Quote(Last =20, Settle = 40) )
aNewSecurity
An object of class "Security"
Slot "Name":
[1] "newSec"
Slot "Price":
An object of class "Quote"
Slot "Last":
[1] 20
Slot "Settle":
[1] 40
I'm not sufficiently knowledgeable to know if separating Quote items from Security items is needed in this domain.
Reference Classes only seem to accept the basic/standard object types are permitted. For instance, I want a chron object but this does not allow me to define it:
> newclass <- setRefClass("newclass",fields=list(time="chron"))
Error in refClassInformation(Class, contains, fields, methods, where) :
class "chron" for field 'time' is not defined
Is this a limitation or there is a better way? I tried maybe setting it in the initialize method but apparently this is not the way to go either:
> newclass <- setRefClass("newclass",
+ fields=list(time="numeric"),
+ methods=list(initialize=function() time <<- as.chron(time)))
library(chron)
> x <- newclass(time=as.chron("2011-01-01"))
Error in .Object$initialize(...) : unused argument (time = 14975)
I think that you need to register your non standard class using setOldclass first.
require(chron)
dts <- dates(c("05/20/13", "06/10/13"))
tms <- times(c("19:30:00", "22:30:05"))
setOldClass("chron")
newclass <- setRefClass("newclass",
fields = list(time = "chron"))
mydate <- newclass(time = chron(dates = dts, times = tms))
mydate$time
## [1] (05/20/13 19:30:00) (06/10/13 22:30:05)
I am getting the message
Error in parent.frame() : node stack overflow
Error during wrapup: node stack overflow
when I try to construct an object using the S4 command "as", but only when a superclass is declared "VIRTUAL".
The class hierarchy is as follows:
PivotBasic contains Pivot contains Model
The setClass commands for Pivot and Pivot Basic and the constructor for PivotBasic are below. Class Pivot does not have a constructor. The Model constructor is too big to insert here.
This is really not a big deal (I think) because everything works fine if the "VIRTUAL" keyword is removed from the representation argument of setClass. But I am curious about the reason for the problem. Would anyone have insights on it?
Thanks,
Fernando Saldanha
setClass(Class = "Pivot",
representation = representation(
pivotName = "character",
pivotNames = "character",
pivotData = "data.frame",
"VIRTUAL"
),
contains = "Model"
)
setClass(Class = "PivotBasic",
representation = representation(),
contains = "Pivot"
)
pivotBasic <- function(
portfolio,
assets,
controlVariableList,
pivotData = NULL, # pivotName is ignored if pivotData is not null
pivotName = "N_WEEKDAY_3_6",
firstPredictionDate = as.Date(integer(), origin = "1970-01-01"),
name = NULL,
tags = "Event"
) {
if (missing(portfolio)) stop("[PivotBasic: pivotBasic] - Missing portfolio argument")
if (missing(assets)) stop("[PivotBasic: pivotBasic] - Missing assets argument")
if (missing(controlVariableList)) stop("[PivotBasic: pivotBasic] - Missing controlVariableList argument")
object <- model(
portfolio,
assets,
controlVariableList,
firstPredictionDate,
name,
tags)
# The error message happens when this command is executed
mdl <- as(object, "PivotBasic")
# Other code
mdl
} # end pivotBasic
Is this a minimal example that illustrates your problem
.Model <- setClass(Class = "Model",
representation=representation(x="integer")
)
setClass(Class = "Pivot",
representation = representation("VIRTUAL"),
contains = "Model"
)
.PivotBasic <- setClass(Class = "PivotBasic",
contains = "Pivot"
)
This generates an error
> as(.Model(), "PivotBasic")
Error: evaluation nested too deeply: infinite recursion / options(expressions=)?
> R.version.string
[1] "R version 3.0.0 Patched (2013-04-15 r62590)"
but might generate an error like you see under an earlier version of R. This thread on the R-devel mailing list is relevant, where a solution is to define a setIs method such as
setIs("PivotBasic", "Model",
coerce = function(from) .PivotBasic(x = from#x),
replace = function(from, value) {
from#x = value#x
from
}
)
I think of setIs as part of the class definition. If there are many slots needing copying, then a further work-around might be, in the replace function,
nms <- intersect(slotNames(value), slotNames(from))
for (nm in nms)
slot(from, nm) <- slot(value, nm)
from
but the underlying issue is really in S4's implementation. A cost to removing the "VIRTUAL" specification is that it compromises your class design, and presumably the formalism of the S4 system is what motivated your choice in the first place; maybe that's not such a bad cost when faced with the alternatives.
Looking through Hadley Wickham's S4 wiki:
https://github.com/hadley/devtools/wiki/S4
setClass("Person", representation(name = "character", age = "numeric"),
prototype(name = NA_character_, age = NA_real_))
hadley <- new("Person", name = "Hadley")
How can we design a constructor for Person (like this)
Person<-function(name=NA,age=NA){
new("Person",name=name,age=age)
}
that doesn't do this:
> Person()
Error in validObject(.Object) :
invalid class "Person" object: 1: invalid object for slot "name" in class "Person": got class "logical", should be or extend class "character"
invalid class "Person" object: 2: invalid object for slot "age" in class "Person": got class "logical", should be or extend class "numeric"
It looks like the answer is right there in your example:
Person<-function(name=NA_character_,age=NA_real_){
new("Person",name=name,age=age)
}
yields
> Person()
An object of class "Person"
Slot "name":
[1] NA
Slot "age":
[1] NA
> Person("Moi")
An object of class "Person"
Slot "name":
[1] "Moi"
Slot "age":
[1] NA
> Person("Moi", 42)
An object of class "Person"
Slot "name":
[1] "Moi"
Slot "age":
[1] 42
However, that is fairly un-S4 and duplicates the default values already assigned in the class definition. Maybe you'd prefer to do
Person <- function(...) new("Person",...)
and sacrifice the ability to call without named arguments?
I'd prefer giving the end-user some hints about argument types than the suggestion to use ... by #themel. Also forgoing the prototype and using length(x#name) == 0 as an indication that the field is un-initialized, using a People class rather than Person, reflecting the vectorized structure of R, and using ... in the constructor so derived classes can also use the constructor.
setClass("People",
representation=representation(
firstNames="character",
ages="numeric"),
validity=function(object) {
if (length(object#firstNames) != length(object#ages))
"'firstNames' and 'ages' must have same length"
else TRUE
})
People = function(firstNames=character(), ages=numeric(), ...)
new("People", firstNames=firstNames, ages=ages, ...)
And
People(c("Me", "Myself", "I"), ages=c(NA_real_, 42, 12))
At the moment, I am switching from Python to R and I am trying to write some simple code to price a portfolio, using Jeff Ryan's Ibrokers package. I would like to have a field of class twsconn in one of my objects
setClass( "MktAsset",
representation( IB.id = "character",
asset.type = "factor",
ccy = "factor",
IB.conn = "twsconn") )
but the system does not seem happy about it
Msg is
In .completeClassSlots(ClassDef, where) :
undefined slot classes in definition of "MktAsset": IB.connection(class "twsconn")
but when I ask the class of tws (initialized with tws <- twsConnect(), it returns
[1] "twsconn" "environment"
I tried to go through the code to check for the existence of a class twsconn but, I found nothing.
Can someone help?
Thanks a lot
The issue is S3 in S4. This should work:
setOldClass("twsconn") # this is what you are missing
setClass( "MktAsset",
representation( IB.id = "character",
asset.type = "factor",
ccy = "factor",
IB.conn = "twsconn") )
# [1] "MktAsset"
a <- new("MktAsset")
ibg <- ibgConnect() # connect to IB Gateway
a#IB.conn <- ibg
a
An object of class "MktAsset"
Slot "IB.id":
character(0)
Slot "asset.type":
factor(0)
Levels:
Slot "ccy":
factor(0)
Levels:
Slot "IB.conn":
<twsConnection,1 # 20110325 13:15:22 CST, nextId=1>
If you're able to come to R/Finance in Chicago in April www.RinFinance.com, I'll be doing a two-hour workshop on Friday
morning (April 29th) regarding IBrokers (and algorithmic trading in general with R)
that would be of interest I suspect.