Bug or Feature in R's version 3.3 class constructing - r

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

Define particular slot as separate class R

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.

defining non-standard classes in Reference Class object

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)

Why am I getting the message "node stack overflow" when the superclass is "VIRTUAL"?

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.

S4 constructors and prototypes

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))

IBrokers R package: issue with class twsconn (R)

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.

Resources