I'm trying to call the checkm function from within another function that accepts a formula as a parameter. I'm getting an object not found error. Here is the minimal implementation and error.
library(lrmest)
data(pcd)
form<-formula(Y~X1+X2+X3+X4)
checkm(form,data=pcd)
Wrap<-function(f){
checkm(f,data=pcd)
}
Wrap(form)
The error is:
Error in model.frame(formula = f, data = pcd, NULL) :
object 'f' not found
Called from: eval(expr, envir, enclos)
My guess from reading around is this has to do with my not understanding environments or promises but given that I don't understand them, I'm probably wrong.
Any quick fixes?
One quick fix is to change the name of your formula argument. It happens to conflict with the eval(cal) call within checkm. I suspect #joran is right that this isn't your fault. This works:
library(lrmest)
data(pcd)
form<-Y~X1+X2+X3+X4
checkm(form,data=pcd)
Wrap<-function(formula){
checkm(formula,data=pcd)
}
Wrap(form)
As #joran pointed out, there is a bug/error in the function caused from not using the correct frame to evaluate the command. If you swap out checkm for lm you'll see it runs just fine. You can create your own function that changes just that one line of code with
checkm2<-checkm
body(checkm2)[[6]]<-quote(cal <- eval(cal, parent.frame()))
And then run
library(lrmest)
data(pcd)
form<-formula(Y~X1+X2+X3+X4)
checkm2(form,data=pcd)
Wrap<-function(f){
checkm2(f,data=pcd)
}
Wrap(form)
and everything seems to run properly. So that just appears to be the fault of the people who wrote the code. You might consider contacting them to file a bug report.
Related
I am trying to run a power analysis using a MonteCarlo approach in R.
I have created a function of two parameters that does output a boolean (tested manually for all relevant values of the parameters). I also have run baby-examples of the MonteCarlo function to make sure that I understand it and that it works well.
Yet when I try to run the real thing, I get the following error message:
Error in parse(text = all_funcs_found[i]) : <text>:1:1: unexpected '::'
1: ::
I read through the source code of the MonteCarlo function (which I found here) and found
#loop through non-primitive functions used in func and check from which package they are
for(i in 1:length(all_funcs_found)){
if(environmentName(environment(eval(parse(text=all_funcs_found[i]))))%in%env_names){
packages<-c(packages,env_names[which(env_names==environmentName(environment(eval(parse(text=all_funcs_found[i])))))])
}
}
which doesn't really make sense to me - why should there be a problem there?
Thank you for any ideas.
I found the answer: the function I wrote was calling a function from a specific library in the form libraryname::functionname.
This works OK if you use the function once manually, but makes MonteCarlo break.
I solved the problem by first loading the relevant library, then removing the 'libraryname::' part from the definition of the main function. MonteCarlo then runs just fine.
Hope you can give me a quick help:
I have a function that works perfect as run in the global envir. When I eval the function from my own package it gives me an error. I can't figure out what the problem is. Seem so random to me.
catTableFun(aaa,grouped_by = "varNameAsString",preview=T) #from global envir works as expected
elricoFuns::catTableFun(aaa,grouped_by = "varNameAsString",preview=T) # identical function run from package gives the following error
Error:
#Error in get(grouped_by) : object 'varNameAsString' not found
Its such a construct causing the error. But why?
setDT(x)
gnLevels <- x[,get(grouped_by),drop=F]
I'm sorry I cant give you some rep example and this is a broad question, but I hope someone has encountered a similar phenomenon or has an educated guess about it.
I am fairly new to R, so my apologies if this question is a bit silly.
I am calling a function in an external package ('mmlcr', although I don't think that is directly relevant to my problem), and one of the required inputs (data) is a data.frame. I compose the data.frame from various data using the following approach (simplified for illustration):
#id, Time, and value are vectors created elsewhere in the code.
myData = data.frame(a=id, b=Time, c=value)
out <- mmlcr( input1, input2, data=myData, input4)
Which throws the error:
Error in is.data.frame(data) : object 'myData' not found
The debugger indicates that this error is thrown during the mmlcr() call.
I then added a print(ls()) immediately prior to the mmlcr() call, and the output confirmed that "myData" was in my function workspace; further is.data.frame(myData) returned TRUE. So it seems that "myData" is successfully being created, but for some reason it is not passing into the mmlcr() function properly. (Commenting this line causes no error to be thrown, so I'm pretty sure this is the problematic line).
However, when I put the exact same code in a script (i.e., not within a function block), no such error is thrown and the output is as expected. Thus, I assume there is some scoping issue that arises.
I have tried both assignment approaches:
myData = data.frame(a=id, b=Time, c=value)
myData <- data.frame(a=id, b=Time, c=value)
and both give me the same error. I admit that I don't fully understand the scope model in R (I've read about the differences between = and <- and I think I get it, but I'm not sure).
Any advice you can offer would be appreciated.
MMLCR is now deprecated and you should search for some alternatives. Without looking too much into it, I sleuthed through an old repo and found the culprit:
m <- eval(m, data)
in the function mmlcr.default. There are a lot of reasons why this is bad, but scoping is the big one. R has this issue with the subset.data.frame function, see my old SO question. Rather than modify the source code, I would find a way to do your function with a subroutine using a for, repeat, or while loop.
I know something similar has been asked before here on SO, but the solution given there doesn't seem to apply in my case.
I'm trying to follow convention in creating a package by referring to functions exported from other namespaces and avoiding use of require() within a function.
I'm basically trying to prevent a function taking too long to run. For example,
fun <- function(i){
require(R.utils)
setTimeLimit(elapsed=10, transient=TRUE) # prevent taking more than 10secs
return(i^i)
}
>fun(10)
Works fine, but if I try:
require(R.utils)
fun <- function(i){
R.utils:::setTimeLimit(elapsed=10, transient=TRUE) # prevent taking more than 10secs
return(i^i)
}
>fun(10)
I get:
Error in get(name, envir = asNamespace(pkg), inherits = FALSE) :
object 'setTimeLimit' not found
Changing ::: to :: doesn't change this behavior.
I'm open to any simpler methods to achieving the same objective.
Also is it really so bad to have require() calls inside a function?
Many thanks!
EDIT:
If import works then great, thanks. Still in development so wanted to make sure it would be OK.
EDIT:
Apologies, it's there in base. Not sure how I missed this; I was originally using R.utils::evalWithTimeout and must have assumed both were in the same package. *looks sheepish*
I'm just posting this to prevent the question from showing up as unanswered, but will be glad to accept another...
isTRUE("setTimeLimit" %in% ls(getNamespace("base"), all.names=TRUE))
I'm facing a strange issue in R.
Consider the following code (a really simplified version of the real code but still having the problem) :
library(timeSeries)
tryCatch(
{
specificWeekDay <- 2
currTs <- timeSeries(c(1,2),c('2012-01-01','2012-01-02'),
format='%Y-%m-%d',units='A')
# just 2 dates out of range
start <- time(currTs)[2]+100*24*3600
end <- time(currTs)[2]+110*24*3600
# this line returns an empty timeSeries
currTs <- window(currTs,start=start,end=end)
message("Up to now, everything is OK")
# this is the line with the uncatchable error
currTs[!(as.POSIXlt(time(currTs))$wday %in% specificWeekDay),] <- NA
message("I'm after the bugged line !")
},error=function(e){message(e)})
message("End")
When I run that code in RGui, I correctly get the following output:
Up to now, everything is OK
error in evaluating the argument 'i' in
selecting a method for function '[<-': Error in
as.POSIXlt.numeric(time(currTs)) : 'origin' must be supplied
End
Instead, when I run it through RScript (in windows) using the following line:
RScript.exe --vanilla "myscript.R"
I get this output:
Up to now, everything is OK
Execution interrupted
It seems like RScript crashes...
Any idea about the reason?
Is this a timeSeries package bug, or I'm doing something wrong ?
If the latter, what's the right way to be sure to catch all the errors ?
Thanks in advance.
EDIT :
Here's a smaller example reproducing the issue that doesn't use timeSeries package. To test it, just run it as described above:
library(methods)
# define a generic function
setGeneric("foo",
function(x, ...){standardGeneric("foo")})
# set a method for the generic function
setMethod("foo", signature("character"),
function(x) {x})
tryCatch(
{
foo("abc")
foo(notExisting)
},error=function(e)print(e))
It seems something related to generic method dispatching; when an argument of a method causes an error, the dispatcher cannot find the signature of the method and conseguently raises an exception that tryCatch function seems unable to handle when run through RScript.
Strangely, it doesn't happen for example with print(notExisting); in that case the exception is correctly handled.
Any idea about the reason and how to catch this kind of errors ?
Note:
I'm using R-2.14.2 on Windows 7
The issue is in the way the internal C code implementing S4 method dispatch tries to catch and handle some errors and how the non-interactive case is treated in this approach. A work-around should be in place in R-devel and R-patched soon.
Work-around now committed to R-devel and R-patched.
Information about tryCatch() [that the OP already knew and used but I didn't notice]
I think you are missing that your tryCatch() is not doing anything special with the error, hence you are raising an error in the normal fashion. In interactive use the error is thrown and handled in the usual fashion, but an error inside a script run in a non-interactive session (a la Rscript) will abort the running script.
tryCatch() is a complex function that allows the potential to trap and handle all sorts of events in R, not just errors. However by default it is set up to mimic the standard R error handling procedure; basically allow the error to be thrown and reported by R. If you want R to do anything other than the basic behaviour then you need to add a specific handler for the error:
> e <- simpleError("test error")
> tryCatch(foo, error = function(e) e,
+ finally = writeLines("There was a problem!"))
There was a problem!
<simpleError in doTryCatch(return(expr), name, parentenv, handler): object 'foo'
not found>
I suggest you read ?tryCatch in more detail to understand better what it does.
An alternative is to use try(). To modify your script I would just do:
# this is the line with the uncatchable error
tried <- try(currTs[!(as.POSIXlt(time(currTs))$wday %in% specificWeekDay),] <- NA,
silent = TRUE)
if(inherits(tried, "try-error")) {
writeLines("There was an error!")
} else {
writeLines("Everything worked fine!")
}
The key bit is to save the object returned from try() so you can test the class, and to have try() operate silently. Consider the difference:
> bar <- try(foo)
Error in try(foo) : object 'foo' not found
> bar <- try(foo, silent = TRUE)
> class(bar)
[1] "try-error"
Note that in the first call above, the error is caught and reported as a message. In the second, it is not reported. In both cases an object of class "try-error" is returned.
Internally, try() is written as a single call to tryCatch() which sets up a custom function for the error handler which reports the error as a message and sets up the returned object. You might wish to study the R code for try() as another example of using tryCatch().