R S4 object datatype hash - r

Is there a datatype for hash? I tried to genereate a class with datatype character for hash values but I got error:
Error in validObject(.Object) : invalid class "Picture" object: 1:
invalid object for slot "mD5sum" in class "Picture": got class "hash",
should be or extend class "character" invalid class "Picture" object
2: invalid object for slot "sHA1sum" in class "Picture": got class
"hash", should be or extend class "character" Calls: <.....
Generate class code:
setClass("Picture", slots=list(id="numeric", mD5sum="character", sHA1sum="character"))
Adding data to class (this gives error):
md5sum <- as.character(openssl::md5(file(full_file_path)))
sha1sum <- as.character(openssl::sha1(file(full_file_path)))
pic_obj <- new("Picture", id=1, mD5sum=md5sum, sHA1sum=sha1sum)
Full code chunk:
```{r}
setClass("Picture", slots=list(id="numeric", mD5sum="character", sHA1sum="character"))
full_file_path <- "testphoto.JPG"
md5sum <- as.character(openssl::md5(file(full_file_path)))
sha1sum <- as.character(openssl::sha1(file(full_file_path)))
pic_obj <- new("Picture", id=1, mD5sum=md5sum, sHA1sum=sha1sum)
```

No, hash is not an atomic type (the closest idea R has to a "data type"). Hash values (such as from openssl::md5) are generally output as character (though in principle they could be integer if the output was small enough).
If you want to know whether a class exists or not, you can use isClass:
> isClass("hash")
[1] FALSE
> isClass("character")
[1] TRUE

Related

R Comparison of two SummarizedExperiment objects

My unit test fails on comparing reference and expected SummarizedExperiment objects. Error message:
> expect_identical(target, current)
Error: `target` not identical to `current`.
Attributes: < Component “assays”: Class definitions are not identical >
MWE:
LINK TO DATASET
Code:
load("se-comparison.Rdata")
library(SummarizedExperiment)
library(testthat)
expect_identical(target, current)
# expect_identical() uses attr.all.equal() to compare S4 objects so check this
attr.all.equal(target, current)
# ok, check the attributes
cur <- attributes(current)
tar <- attributes(target)
class(cur$assays)
class(tar$assays)
expect_identical(
cur$assays,
tar$assays
)
expect_identical(
class(cur$assays),
class(tar$assays)
)
Output:
> library(SummarizedExperiment)
> library(testthat)
> expect_identical(target, current)
Error: `target` not identical to `current`.
Attributes: < Component “assays”: Class definitions are not identical >
> # expect_identical() uses attr.all.equal() to compare S4 objects so check this
> attr.all.equal(target, current)
[1] "Attributes: < Component “assays”: Class definitions are not identical >"
> # ok, check the attributes
> cur <- attributes(current)
> tar <- attributes(target)
> class(cur$assays)
[1] "ShallowSimpleListAssays"
attr(,"package")
[1] "SummarizedExperiment"
> class(tar$assays)
[1] "ShallowSimpleListAssays"
attr(,"package")
[1] "SummarizedExperiment"
> cur$assays
Reference class object of class "ShallowSimpleListAssays"
Field "data":
List of length 1
names(1): counts
> tar$assays
Reference class object of class "ShallowSimpleListAssays"
Field "data":
List of length 1
names(1): counts
> expect_identical(
+ cur$assays,
+ tar$assays
+ )
Error: cur$assays not identical to tar$assays.
Class definitions are not identical
> expect_identical(
+ class(cur$assays),
+ class(tar$assays)
+ )
>
Any ideas why comparison fails?
Not sure why it fails in general, but attr.all.equal compares class definitions returned by getClass method (if available). In this case, getClass for each $assays object returns class definition that differs in fieldPrototypes and refMethods (environment strings differ). This causes identical to fail.
Compare:
str(class(cur$assays))
str(cur$assays$getClass())
A workaround would be to skip checking attributes: expect_equal(target, current, check.attributes = FALSE).
As a side note, this also works fine (note that I use here a getter method for SummarizedExperiment class instead of $assays):
expect_equal(
assays(current),
assays(target)
)

Bug or Feature in R's version 3.3 class constructing

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?

Using fields from object in for-loop | twitteR

I am kind of a newbie to R. I am trying to build a function to retrieve and output all the dimensions. I am using the twitteR package which has an object 'user'. I use the getUser() which outputs a 'user' class type of object. As a part of the twitteR packages documentation, this object is not subsettable but does have fields such as names, screenNames, description, etc., e.g.:
> g <- getUser("CNN")
> g$name
[1] "CNN"
> g$screenName
[1] "CNN"
> g$description
[1] "Bringing you breaking news and the most talked about stories. Join the conversation and let’s connect!"
> g$statusesCount
[1] 35605
> g$followersCount
[1] 10542191
This is my function that I am trying to create and am struggling with:
userInfo <- function(user) {
userDims<- c("name", "screenName", "id", "lastStatus", "description", "statusesCount", "followersCount", "favoritesCount", "friendsCount")
for(i in seq_along(userDims)){
userObj <- getUser(user)
userObj$userDims[i]
}
}
My question is: How do I concatenate userObj$ with each entry in userDim without getting this error:
Error in envRefInferField(x, what, getClass(class(x)), selfEnv) :
‘userDims’ is not a valid field or method name for reference class “user”**

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)

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

Resources