I can't figure out what I'm missing. Following Situation:
I wrote a R-Package lets call it "pkg_A"
It depends on "Rcpp" and I have a Module loaded and a class set up like :
Rcpp::loadModule("pkg_A_modul", what = "pkg_A_cppClass_A")
cppClass_A <- setRcppClass(
Class = "pkg_A_cppClass_A",
CppClass = "pkg_A_cppClass_A",
module = "pkg_A_modul",
fields = c(
remark = "character"
)
)
and a additional constructor
classA <- function(a,b){
# some stuff
tmpObj <- cppClass_A()
# some more stuff
return(tmpObj)
}
class(classA ) <- "classA "
The only Thing what I export to the NAMESPACE is the classA function/class.
That all works fine and I can build that package without any warnings and even can check it with "--as-cran" flag.
Now I want to build a second package on top of that package, lets call that "pkg_B" Therefore I list "pkg_A" in the DESCRIPTION Depends of "pkg_B"
as well as I load the class with importFrom(pkg_A, classA) in the NAMESPACE of "pkg_B".
Now I want to implement a class
classB <- setRefClass(
"classB",
contains = c("classA"),
fields = c( b = "numeric)
)
But when I now want to build "pkg_B" I get the error:
Error in getClass(what, where = where) : "classA" is not a defined
class
I also tried to use the "pkg_A_cppClass_A" instead or imprt the whole pkg_A or use pkg_A::classA. Nothing changed.
Hope the question is complete enough. If you missing some info let me know.
Thankful for any suggestions!
Related
I am using rpy2 to import a library from CRAN repository called "MatrixEQTL" to run in within Python using importr, here is my attempt:
import rpy2.robjects as robjects
from rpy2.robjects.packages import importr
robjects.r('install.packages("MatrixEQTL")')
mtrql = importr('MatrixEQTL')
I am trying to access both class fields as well as class methods but I failed here is what the class looks like when printing into the python shell:
# to view class SlicedData of MatrixEQTL R package
print(mtrql.SlicedData)
Generator for class "SlicedData":
Class fields:
Name: dataEnv nSlices1 rowNameSlices
Class: environment numeric list
Name: columnNames fileDelimiter fileSkipColumns
Class: character character numeric
Name: fileSkipRows fileSliceSize fileOmitCharacters
Class: numeric numeric character
Class Methods:
"Clear", "show#envRefClass", "nSlices", "getRefClass", "export",
"initialize", "CombineInOneSlice", "callSuper", "initFields", "nCols",
"getClass", "RowStandardizeCentered", "import", "SaveFile", "RowReorder",
"setSlice", "getSlice", "RowReorderSimple", "CreateFromMatrix", "nRows",
"ResliceCombined", "LoadFile", "ColumnSubsample", "SetNanRowMean",
"setSliceRaw", "getSliceRaw", "copy", "RowMatrixMultiply", "usingMethods",
"GetAllRowNames", "RowRemoveZeroEps", "field", ".objectParent",
"IsCombined", "untrace", "trace", "Clone", "GetNRowsInSlice",
".objectPackage", "show", "FindRow"
Reference Superclasses:
"envRefClass"
I want to access for instance class field say fileDelimiter and also class Methods say LoadFile but I couldn't, here is also my attempt to access class method LoadFile and the error message that generated:
# If I try to run this without "()"
data = mtrql.SlicedData
load_my_file = data.LoadFile(file)
data = data.LoadFile(file)
AttributeError: 'DocumentedSTFunction' object has no attribute 'LoadFile'
# And that's my attempt for when adding "()" to the class name
data = mtrql.SlicedData
load_my_file = data.LoadFile(file)
data = data.LoadFile(file)
AttributeError: 'RS4' object has no attribute 'LoadFile'
I tried to look for a solution to this issue but I wasn't successful, please help me understand and solve this issue.
Thank you so much in advance.
mtrql.SlicedData is a "Generator", that is a constructor. In R that means a function (that will return an instance of the class), which is why mtrql.SlicedData is an R function with rpy2.
Consider the following example from the R documentation (https://rdrr.io/r/methods/Introduction.html):
import rpy2.robjects as ro
Pos = ro.r("""
setClass("Pos", slots = c(latitude = "numeric", longitude = "numeric",
altitude = "numeric"))
""")
With rpy2, the object Pos is an R function:
>>> type(Pos)
rpy2.robjects.functions.SignatureTranslatedFunction
However that function object has an S3 class in R (there are several OOP systems in R, 2 of them coexisting in standard R unfortunately).
>>> tuple(Pos.rclass)
('classGeneratorFunction',)
A specific print function is implemented for this S3 class, and it will use the attributes package and className for the object (the R function-that-is-in-fact-a-Generator) to display all the info about the clas you are seeing.
Since this is a constructor, to create an instance you can do:
pos = Pos()
or
pos = Pos(latitude=0, longitude=0, altitude=-10)
The instance will have instance attributes (and methods)
>>> tuple(pos.list_attrs())
('latitude', 'longitude', 'altitude', 'class')
>>> tuple(pos.do_slot('altitude'))
(-10,)
With your specific example, you probably want something like:
slidata = mtrql.SlicedData()
slidata.do_slot('LoadFile')(file)
The documentation can provide more information about R S4 classes in rpy2, and how to make wrapper classes in Python that map attributes and methods.
https://rpy2.github.io/doc/v3.3.x/html/robjects_oop.html#s4-objects
I am creating an RC class and while trying to print(.self$something) within a class method I am getting:
Error in print(.self$something) : unused argument (.self$something)
I am sort of new to R, so am I missing something here?
This is for an assignment which asks us to use RC classes, using R6 is not an option.
myclass <- setRefClass("myclass",
fields = list (
formula = "formula",
data = "data.frame",
something = "numeric"
),
methods = list (
initialize = function(formula, data) {
...
},
print = function() {
...
print(.self$something)
},
)
)
a <- myclass$new(formula,data)
a$print()
> Error in print(.self$something) : unused argument (.self$something)
Edit: Extra info, if I try a$something I get what I should get.
Try to use cat in your print function, you are now in your local print function environment and trying to call your system "print" function. I suggest you use cat as follows:
cat(.self$something)
It will do the job
As #Mohammed mentions, this happened because I was in printing within my own print environment. Though cat() could be an option, later I faced other issues in which cat did not print the object (that could be a thread on its own so I will not go deeper on that here).
What I ended up doing was calling the print function for that specific data type. For instance, if something was a data.frame I called print.data.frame(.self$something) and worked as expected.
After struggling with documenting a S4 class with roxygen2, I decided to take a step back and create a minimum example using package.skeleton, promptClass, and promptMethod.
My problem is that R CMD check still gives a warning about "undocumented code objects", although I think that I have documented them properly.
The files I have now are:
testClass.R:
setClass("testClass",
slots = c(a = "numeric"),
prototype = prototype( a = 0 ),
validity = function(object) return(TRUE))
setGeneric(name = "testMethod",
def = function(object, ...) standardGeneric("testMethod") )
setMethod(f = "testMethod", signature = "testClass",
definition=function(object, x)
{
cat("testMethod:",x,"\n")
invisible(object)
}
)
testClass-class.Rd
\name{testClass-class}
\Rdversion{1.1}
\docType{class}
\alias{testClass-class}
%%\alias{testMethod,testClass-method}
\title{Class \code{"testClass"}}
\description{bla bla}
\section{Objects from the Class}{bla bla}
\section{Slots}{\describe{\item{\code{a}:}{Object of class \code{"numeric"} ~~ }}}
\section{Methods}{\describe{\item{testMethod}{\code{signature(object = "testClass")}: ... }}}
\keyword{classes}
and testMethod.Rd
\name{testMethod-methods}
\docType{methods}
\alias{testMethod-methods}
\alias{testMethod,testClass-method}
\title{ ~~ Methods for Function \code{testMethod} ~~}
\description{blabla}
\section{Methods}{
\describe{\item{\code{signature(object = "testClass")}}{blabla}}}
\keyword{methods}
There is also a package documentation file, but I think it is not relevant here.
R CMD check gives:
* checking for missing documentation entries ... WARNING
Undocumented code objects:
‘testMethod’
All user-level objects in a package should have documentation entries.
See chapter ‘Writing R documentation files’ in the ‘Writing R
Extensions’ manual.
I have consulted these sections, and what I took from these is that I needed at least an alias to generic,signature-list-method, which in this case would be alias{testMethod,testClass-method} which was placed in the documentation file automatically by my call of promtMethod (I have commented it out from the class .Rd file because it was duplicated there).
What do I need to change in the .Rd file to get rid of this warning?
In the meanwhile, I figured out the problem. It seems that I also needed to ass \alias{testMethod} to the .Rd file. I find it strange, however, that the file generated by promptMethod did not include this alias.
I'm looking for a way to tell an instance of a reference class to forget one of its method definitions. For example, I create the class MyReferenceClass and an instance called my_object I can call the method print_hello and everything works:
MyReferenceClass <- setRefClass("MyReferenceClass",
methods = list(
print_hello = function(){
print("hello")
}
)
)
my_object <- MyReferenceClass$new()
my_object$print_hello() # "hello"
If I update the class definition by adding a new method (print_goodbye) my existing object will be able to use it. But if I change a previously defined method (print_hello), it won't update:
MyReferenceClass <- setRefClass("MyReferenceClass",
methods = list(
print_hello = function(){
print("hello_again")
},
print_goodbye = function(){
print("goodbye")
}
)
)
my_object$print_goodbye() # "goodbye" => it works
my_object$print_hello() # "hello" => it doesn't work
Is there a way to tell my_object to forget about its definition of print_hello? This doesn't work: my_object$print_hello <<- NULL
AFAIK the answer is no when trying to inform the object about the class def change "after the fact", i.e. after it has been instantiated/created.
Once you created an instance of a S4 Class, that object is "bound" to the class def as it was when you created the object. And in my opinion this makes perfect sense. Not sure if the "successful" update for formerly missing methods (i.e. print_goodbye()) simply works "by accident" or actually is the desired behavior.
Recommended way to deal with updated class defs
My recommendation: if you decide you want/need to update your class defs, you're just safer off by re-sourcing your entire project code. That way you make sure everything is in place before you create actual instances. I'd consider anything else to be quite a hack that stands on very shaky grounds.
If you decide to hack anyway
There might be some dirty way to hack the hidden .refClassDef object field of an Reference Class instance that actually contains the class def (see my_object$.refClassDef). But setting this field (i.e. using <- on it) didn't work:
my_object$.refClassDef <- MyReferenceClass
Error in envRefSetField(x, what, refObjectClass(x), selfEnv, value) :
'.refClassDef' is not a field in class "MyReferenceClass"
Neither did an explicit assignment via assign():
assign(".refClassDef", MyReferenceClass, my_object)
Error in assign(".refClassDef", MyReferenceClass, my_object) :
cannot change value of locked binding for '.refClassDef'
An even deeper hack would probably involve looking at attributes(my_object$.refClassDef).
There you might find the actual pieces that make up the ref class def. However, I don't know if even changing anything there would be "immediately" reflected.
Also, resetClass() might give you some more insights.
UPDATE: 2014-03-19
For handling your caching-approach two approaches come to mind:
1. The most evident way: use copy()
See ?setRefClass
MyReferenceClass <- setRefClass("MyReferenceClass",
methods = list(
print_hello = function(){
print("hello")
}
)
)
my_object <- MyReferenceClass$new()
MyReferenceClass <- setRefClass("MyReferenceClass",
methods = list(
print_hello = function(){
print("hello_again")
},
print_goodbye = function(){
print("goodbye")
}
)
)
Before copying:
my_object$print_hello()
[1] "hello"
After copying:
my_object <- my_object$copy()
my_object$print_hello()
[1] "hello_again"
2. Hacking at attributes(my_object$.refClassDef)$refMethods (OUTLINE, NOT WORKING YET)
Even though I wouldn't recommend actually relying on something like this, hacks are always a great way to get a deeper understanding of how things work.
In this case, we could try to modify attributes(my_object$.refClassDef)$refMethods which is an environment that contains the actual method defs as I'm guessing that this is where the object "looks" when a method is called.
It's no problem overwriting the actual method defs, yet it seems to have no immediate effect. I'm guessing that there are more "links" to the "old" class def involved that would need to be updated manually in a similar way.
Note that my_object still features the method print_hello that prints "hello":
attributes(my_object$.refClassDef)$refMethods$print_hello
Class method definition for method print_hello()
function ()
{
print("hello")
}
This is how an overwriting function might look like:
ensureRecentMethods <- function(obj, classname) {
## Get generator //
gen <- getRefClass(classname)
## Get names of methods belonging to the class of 'obj' //
## This will serve as an index for the update
idx1 <- names(Filter(function(x) {attr(x, "refClassName") == class(obj)},
as.list(attributes(obj$.refClassDef)$refMethods))
)
#idx2 <- names(Filter(function(x) {attr(x, "refClassName")==gen$className},
# as.list(gen$def#refMethods)
#))
## Note:
## 'idx2' could be used to enforce some validity checks such as
## "all old methods must also be present in the updated class def"
## Overwrite //
for (ii in idx1) {
## Note how we are overwriting the old method defs in environment
## 'attributes(obj$.refClassDef)$refMethods' with the updated
## definitions taken from the generator of the updated class
## 'gen$def#refMethods[[ii]]' by making use of the index retrieved
## one step before ('idx1')
expr <- substitute(
assign(x=X, value=VALUE, envir=ENVIR),
list(
X=ii,
VALUE=gen$def#refMethods[[ii]],
ENVIR=attributes(obj$.refClassDef)$refMethods
)
)
eval(expr)
}
## As at the end of the day ref class objects are nothing more than
## environments, there is no need to explicitly return the actual
## ref class object 'obj' as the original object has already
## been updated (pass-by-reference vs. pass-by-value)
return(TRUE)
}
Applying it:
ensureRecentMethods(obj=my_object, classname="MyReferenceClass")
Even though the def of print_hello was indeed overwritten, the object still grabs the "old" version somehow:
attributes(my_object$.refClassDef)$refMethods$print_hello
## Note the updated method def!
Class method definition for method print_hello()
function ()
{
print("hello_again")
}
my_object$print_hello()
[1] "hello"
Take advantage of my_class#generator$def#refMethods
How about including an update method in the original class, as did here,
Manual modifications of the class definition of a Reference Class instance
I'm currently programming an R-script which uses a java .jar that makes use of the java/lang/Vector class, which in this case uses a class in a method that is not native. In java source code:
public static Vector<ClassName> methodname(String param)
I found nothing in the documentation of rJava on how to handle a template class like vector and what to write when using jcall or any other method.
I'm currently trying to do something like this:
v <- .jnew("java/util/Vector")
b <- .jcall(v, returnSig = "Ljava/util/Vector", method = "methodname",param)
but R obviously throws an exception:
method methodname with signature (Ljava/lang/String;)Ljava/util/Vector not found
How do I work the template class into this command? Or for that matter, how do I create a vector of a certain class in the first place? Is this possible?
rJava does not know java generics, there is no syntax that will create a Vector of a given type. You can only create Vectors of Objects.
Why are you sticking with the old .jcall api when you can use the J system, which lets you use java objects much more nicely:
> v <- new( J("java.util.Vector") )
> v$add( 1:10 )
[1] TRUE
> v$size()
[1] 1
# code completion
> v$
v$add( v$getClass() v$removeElement(
v$addAll( v$hashCode() v$removeElementAt(
v$addElement( v$indexOf( v$retainAll(
v$capacity() v$insertElementAt( v$set(
v$clear() v$isEmpty() v$setElementAt(
v$clone() v$iterator() v$setSize(
v$contains( v$lastElement() v$size()
v$containsAll( v$lastIndexOf( v$subList(
v$copyInto( v$listIterator( v$toArray(
v$elementAt( v$listIterator() v$toArray()
v$elements() v$notify() v$toString()
v$ensureCapacity( v$notifyAll() v$trimToSize()
v$equals( v$remove( v$wait(
v$firstElement() v$removeAll( v$wait()
v$get( v$removeAllElements()