I'm currently trying to implement support vector machine algorithm for classification and anomaly detection using Oracle R Enterprise (ORE). I've installed the ORE packages in RStudio
and as a sample, I'm trying to execute the following code given in Oracle Docs:
library(ORE)
m <- mtcars
m$gear <- as.factor(m$gear)
m$cyl <- as.factor(m$cyl)
m$vs <- as.factor(m$vs)
m$ID <- 1:nrow(m)
MTCARS <- ore.push(m)
And I got the following error:
Error in .ore.obj() : attempt to apply non-function
I think it is because ore.push() is not recognized but When I searched in the ORE Reference Manual it is clearly defined with an example.
So, what could be its solution?
Have you connected to your database using ore.connect?
ore.connect(user = "<userid", sid = "<sid>"
, host = "<dbserver>"
, password = "<userpwd"
, all=TRUE)
ore.connect - controls whether to automatically connect to ORE inside the closure. This is equivalent to doing an ore.connect call with the same credentials as the client session. The default value is FALSE.
ore.is.connected() ## TRUE
ore.doEval( function(){ ore.is.connected() } ) ## FALSE
ore.doEval( function(){ ore.is.connected() }, ## TRUE
ore.connect=TRUE
)
Therefore it follows this throws an error:
> ore.doEval(
+ function()
+ {
+ require(ORE)
+ ore.load("myData")
+ }
+ )
Error in .oci.GetQuery(conn, statement, data = data, prefetch = prefetch, :
ORA-20000: RQuery error
Error in OREbase:::.ore.dbGetQuery(qry) : attempt to apply non-function
ORA-06512: at "RQSYS.RQEVALIMPL", line 104
ORA-06512: at "RQSYS.RQEVALIMPL", line 101
But this is fine:
> ore.doEval(
+ function()
+ {
+ require(ORE)
+ ore.load("myData")
+ },
+ ore.connect=TRUE
+ )
[1] "FOO" "BAR"
Related
To handle warnings or errors one can use
result = tryCatch({
expr
}, warning = function(w) {
warning-handler-code
}, error = function(e) {
error-handler-code
}, finally = {
cleanup-code
}
but if expr gives a message through simpleMessage, how can I get it? Is there something like?:
message = function(m) {message-handler-code}
Or another function which allows me to capture the message?
Thank you!
Yes, you can use message = just as you can with warning and error:
result = tryCatch({
message("Hello world")
1 + 1
}, message = function(m) {m}
)
result
#> <simpleMessage in message("Hello world"): Hello world
>
It's more likely however that you would want to capture your result and message separately:
result <- withCallingHandlers({
message("Hello world")
1 + 1
}, message = function(m) {
lastMessage <<- m
invokeRestart("muffleMessage")
})
result
#> [1] 2
if(exists("lastMessage")) message(lastMessage)
#> Hello world
tryCatch is the most commonly useful solution for handling conditions.
However, tryCatch aborts execution and returns the value of the handler, rather than resuming execution of the code. This may not always be what you want; sometimes you want to handle a condition and carry on.
R allows this thanks to its incredibly powerful condition system.
For example, you can choose to silence all messages:
suppressMessages(expr)
The nice thing here is that the suppressMessages isn’t magic — it’s a plain old R function and you could write it yourself (but you do need to understand the condition system, and the price for its versatility is that it’s fairly complicated).
To illustrate this, here’s another way of handling messages — using withCallingHandlers — which suppresses the messages, carries on executing the code it’s called with, but at the same time logs the message in a list:
messages = list()
withCallingHandlers({
message('Hello world')
1 + 1
}, message = function (msg) {
messages <<- c(messages, msg)
tryInvokeRestart('muffleMessage')
})
tryInvokeRestart('muffleMessage') is the same method by which suppressMessages works. The only difference is that we added code to store the message.
As a last step, the above can even be wrapped inside a function:
with_logging = function (expr) {
messages = list()
log_message = function (msg) {
messages <<- c(messages, conditionMessage(msg))
tryInvokeRestart('muffleMessage')
}
result = withCallingHandlers(expr, message = log_message)
list(result = result, messages = messages)
}
And to use it:
with_logging({
message('this is a test')
1 + 1
})
$result
[1] 2
$messages
$messages[[1]]
[1] "this is a test\n"
I want to automatically set the value of an argument in a function based on another argument's value.
More specifically, I want to set a timezone value (offset) to automatically adjust time values given the region.
However, my implementation doesn't seem to work (as in the offset is never applied unless I specifically pass it as an argument to the function).
Part of the function (is supposed to) set the offset value based on region's value, and also connect to the corresponding Elasticsearch server.
This is what I have:
if (region == "EU") {
offset = "+00:00:00"
# Code to connect to EU ElasticSearch server
} else if (region == "US") {
offset = "-06:00:00"
# Code to connect to US ElasticSearch server
} else {
paste0(stop("Incorrect region supplied: ", region))
}
The function:
time_function <- function(region, retailer, start_date, end_date, offset = "+00:00:00"){
# Function body
}
(Note that I have set the default value of offset to "+00", otherwise it will throw an error that the argument is missing.)
Clearly I have gone wrong somewhere because the offset is never applied unless I explicitly specify in the argument list.
This is what I want to do:
If region == "US", then set offset to "-06:00:00",
Else if region == "EU", then set offset to "+00:00:00"
Else Error message: "supply valid region"
In short, I am looking to set a conditional argument value.
How can I achieve this?
It turns out I made an oversight in the order of assignment implementations and have just now spotted it.
For those who might be experiencing similar problems, it might be worth highlighting where I went wrong: I set the offset value after it was used, meaning that it was used/processed (using the previous iteration's value) and then it was assigned the new value.
In short, my implementation was completely correct but the order of events was incorrect.
Therefore, make sure that you set the required values before they are processed.
Your code work.
> time_function <- function(region){
+ # Function body
+ if (region == "EU") {
+ offset = "+00:00:00"
+ # Code to connect to EU ElasticSearch server
+ } else if (region == "US") {
+ offset = "-06:00:00"
+ # Code to connect to US ElasticSearch server
+ } else {
+ stop(paste0("Incorrect region supplied: ", region))
+ }
+
+ return(offset)
+ }
>
> time_function("EU")
[1] "+00:00:00"
> time_function("US")
[1] "-06:00:00"
> time_function("CH")
Error in time_function("CH") : Incorrect region supplied: CH
To optimize your code, you can use the switch.
> time_function <- function(region){
+ # Function body
+ offset <- switch(region,
+ EU = "+00:00:00",
+ US = "-06:00:00",
+ stop(paste0("Incorrect region supplied: ", region)))
+
+ return(offset)
+ }
>
> time_function("EU")
[1] "+00:00:00"
> time_function("US")
[1] "-06:00:00"
> time_function("CH")
Error in time_function("CH") : Incorrect region supplied: CH
With two parameters:
> time_function <- function(region){
+ # Function body
+ list2env(switch(region,
+ EU = list(offset = "+00:00:00", con = "EU_con"),
+ US = list(offset = "+00:00:00", con = "US_con"),
+ stop(paste0("Incorrect region supplied: ", region))), envir = environment())
+
+ return(c(offset, con))
+ }
>
> time_function("EU")
[1] "+00:00:00" "EU_con"
> time_function("US")
[1] "+00:00:00" "US_con"
> time_function("CH")
Error in list2env(switch(region, EU = list(offset = "+00:00:00", con = "EU_con"), :
Incorrect region supplied: CH
Displaying error locations with options(show.error.locations = TRUE) doesn't seem to work when handling exceptions with tryCatch. I am trying to display location of the error but I don't know how:
options(show.error.locations = TRUE)
tryCatch({
some_function(...)
}, error = function (e, f, g) {
e <<- e
cat("ERROR: ", e$message, "\nin ")
print(e$call)
})
If I then look at the variable e, the location doesn't seem to be there:
> str(e)
List of 2
$ message: chr "missing value where TRUE/FALSE needed"
$ call : language if (index_smooth == "INDEX") { rescale <- 100/meanMSI[plotbaseyear] ...
- attr(*, "class")= chr [1:3] "simpleError" "error" "condition"
If I don't trap the error, it is printed on the console along with source file and line number. How to do it with tryCatch?
Context
As noted by Willem van Doesburg, it is not possible to use the traceback() function to display where the error occured with tryCatch(), and to my knowledge there is currently no practical way to store the position of the error with base functions in R while using tryCatch .
The idea of a separate error handler
The possible solution I found consists of two parts, the main one is writing an error handler similar to that of Chrispy from "printing stack trace and continuing after error occurs in R" which produces a log with the position of the error.
The second part is capturing this output into a variable, similarly to what was suggested by Ben Bolker in "is it possible to redirect console output to a variable".
The call stack in R seems to be purged when an error is raised and then handled (I might be wrong so any information is welcomed), hence we need to capture the error while it is occuring.
Script with an error
I used an example from one of your previous questions regarding where and R error occured with the following function stored in a file called "TestError.R" which I call in my example bellow:
# TestError.R
f2 <- function(x)
{
if (is.null(x)) "x is Null"
if (x==1) "foo"
}
f <- function(x)
{
f2(x)
}
# The following line will raise an error if executed
f(NULL)
Error tracing function
This is the function I adapted form Chrispy's code as I mentionned above.
Upon execution, if an error is raised, the code underneath will print where the error occured, in the case of the above function, it will print :
"Error occuring: Test.R#9: f2(x)" and "Error occuring: Test.R#14: f(NULL)" meaning the error result from a trouble with the f(NULL) function at line 14 which references the f2() function at line 9
# Error tracing function
withErrorTracing = function(expr, silentSuccess=FALSE) {
hasFailed = FALSE
messages = list()
warnings = list()
errorTracer = function(obj) {
# Storing the call stack
calls = sys.calls()
calls = calls[1:length(calls)-1]
# Keeping the calls only
trace = limitedLabels(c(calls, attr(obj, "calls")))
# Printing the 2nd and 3rd traces that contain the line where the error occured
# This is the part you might want to edit to suit your needs
print(paste0("Error occuring: ", trace[length(trace):1][2:3]))
# Muffle any redundant output of the same message
optionalRestart = function(r) { res = findRestart(r); if (!is.null(res)) invokeRestart(res) }
optionalRestart("muffleMessage")
optionalRestart("muffleWarning")
}
vexpr = withCallingHandlers(withVisible(expr), error=errorTracer)
if (silentSuccess && !hasFailed) {
cat(paste(warnings, collapse=""))
}
if (vexpr$visible) vexpr$value else invisible(vexpr$value)
}
Storing the error position and the message
We call the script TestError.R above and capture the printed output in a variable, here called errorStorage with which we can deal later on or simply display.
errorStorage <- capture.output(tryCatch({
withErrorTracing({source("TestError.R")})
}, error = function(e){
e <<- e
cat("ERROR: ", e$message, "\nin ")
print(e$call)
}))
Hence we keep the value of e with the call and message as well as the position of the error location.
The errorStorage output should be as follow:
[1] "[1] \"Error occuring: Test.R#9: f2(x)\" \"Error occuring: Test.R#14: f(NULL)\""
[2] "ERROR: argument is of length zero "
[3] "in if (x == 1) \"foo\""
Hoping this might help.
You can use traceback() in the error handler to show the call stack. Errors in a tryCatch don't produce line numbers. See also the help on traceback. If you use your tryCatch statements defensively, this will help you narrow down the location of the error.
Here is a working example:
## Example of Showing line-number in Try Catch
# set this variable to "error", "warning" or empty ('') to see the different scenarios
case <- "error"
result <- "init value"
tryCatch({
if( case == "error") {
stop( simpleError("Whoops: error") )
}
if( case == "warning") {
stop( simpleWarning("Whoops: warning") )
}
result <- "My result"
},
warning = function (e) {
print(sprintf("caught Warning: %s", e))
traceback(1, max.lines = 1)
},
error = function(e) {
print(sprintf("caught Error: %s", e))
traceback(1, max.lines = 1)
},
finally = {
print(sprintf("And the result is: %s", result))
})
I've got this small snippet for reducing a large system:
# set up the multipliers
g1 = (s+9)/((s)*(s+6)*(s+12)*(s+14))
g2 = ((6)*(s+9)*(s+17))/((s+12)*(s+32)*(s+68))
h1 = 13
h2 = 1/(s+7)
# reduce the system in parts
s1 = (g2)/(1 + (g2)*(h1))
s2 = (s1)*(g1)
s3 = (s2)/(1 + (s2)*(h2))
# now we have a unity feedback
g = s3
show(g)
g should be the reduced equation from doing the operations above. However, I get a bunch of errors when I run the code:
Error : object 's' not found
Error : object 's' not found
Error : object 's' not found
Error : object 'g2' not found
Error : object 's1' not found
Error : object 's2' not found
Error : object 's3' not found
Error : error in evaluating the argument 'object' in selecting a method for function 'show': Error: object 'g' not found
Am I not using equations correctly?
edit: my intentions are to have s as a free variable
In order to evaluate your first line of code, there must be an object s that is already defined.
It sounds like your goal is to create a function that outputs g from a single input s. The below code wraps your calculations in a function called make_g:
make_g <- function(s){
# set up the multipliers
g1 = (s+9)/((s)*(s+6)*(s+12)*(s+14))
g2 = ((6)*(s+9)*(s+17))/((s+12)*(s+32)*(s+68))
h1 = 13
h2 = 1/(s+7)
# reduce the system in parts
s1 = (g2)/(1 + (g2)*(h1))
s2 = (s1)*(g1)
s3 = (s2)/(1 + (s2)*(h2))
# now we have a unity feedback
g = s3
g
}
Now, you can call the functions using whatever value for s you like:
make_g(s = 1)
A question about this R code:
library(RODBC)
ch <- tryCatch(odbcConnect("RTEST"),
warning=function(w){print("FAIL! (warning)");return(NA)},
error=function(e){print(paste("ERROR:",geterrmessage()));return(NA)})
df <- tryCatch(sqlQuery(ch,"SELECT Test from tblTest"),
warning=function(w){print("FAIL! (warning)");return(NA)},
error=function(e){print(paste("ERROR:",geterrmessage()));return(NA)})
odbcClose(ch)
Code works fine for errors (forced by omitting the required paramaters in the code) in both cases (warning- and error part are almost exactly the same): I get a NA value and an errormessage.
Also for an error with sqlQuery (give an invalid DSN): NA value and an errormessage.
But not for warnings with sqlQuery. No message output, but df contains the message (so no NA). Why?
I checked code for sqlQuery and found this:
stat <- odbcQuery(channel, query, rows_at_time)
if (stat == -1L) {
if (errors)
return(odbcGetErrMsg(channel))
else return(invisible(stat))
}
error is parameter to sqlQuery, on default TRUE, so it gives you character vector without error or warning. If you change it to sqlQuery(ch,"SELECT Test from tblTest",FALSE) then df will contain -1 value. This is error code from C-level, but not error in R meaning so tryCatch could not handle it.
I suppose that you need to check if df==-1 after tryCatch.
I ended up with this code. Now I can handle the specific Mysql error_code:
saveText <- function(query, channel, errors = TRUE) {
stat <- odbcQuery(channel, query)
if (stat == -1L) {
if (errors)
err <- odbcGetErrMsg(channel)
else {
err <- invisible(stat)
}
return(err)
}
}