R - Assigning "NA" to objects 'not found' inside a function; is it possible? - r

I am running a data set (in the example, "data object ") through several different functions in R and concatenating the numeric results at the end. See:
a<-median((function1(x=1,dataobject,reps=500)),na.rm=TRUE)
b<-median((function2(x=1,dataobject,reps=500)),na.rm=TRUE)
c<-median((function3(x=1,dataobject,reps=500)),na.rm=TRUE)
d<-median((function4(x=1,dataobject,reps=500)),na.rm=TRUE)
e<-median((function5(x=1,dataobject,reps=500)),na.rm=TRUE)
f<-median((function6(x=1,dataobject,reps=500)),na.rm=TRUE)
c(a,b,c,d,e,f)
However, some of the functions cannot be run with the data set I am using, and so they return an error; e.g. "function3" can't be run so when it gets to the concatenation step it gives "Error: object 'e' not found" and does not return anything. Is there any way to tell R at the concatenation step to assign a value of "NA" to an object that is not found and continue to run the rest of the code instead of stopping? So that the return would be
[1] 99.233 75.435 77.782 92.013 NA 97.558
A simple question, but I could not find any other instances of it being asked. I originally tried to set up a function to run everything and output the concatenated results, but ran into the same problem (when a function can't be run, the entire wrapper function stops as well and I don't know how to tell R to skip something it can't compute).
Any thoughts are greatly appreciated! Thanks!

A couple of solutions I can think of,
Initialize all the variables you plan to use, so they have a default value that you want.
a = b = c = d = e = NA
then run your code. If an error pops up, you will have NA in the variable.
Use "tryCatch". If you are unaware what this is, I recommend reading on it. It lets you handle errors.
Here is an example from your code,
tryCatch({
a<-median((function1(x=1,dataobject,reps=500)),na.rm=TRUE)
},
error = function(err){
print("Error in evaluating a. Initializing it to NA")
a <<- NA
})

Related

declaration of variables in R

I have a problem of using a variable in R Studio. My code is as following. "child_birth" is a vector composed of 49703 strings that indicates some information about the birth of childre. What I did here is to tell whether the last 7 characters in each element of the vector is "at home". So I used a for loop and an if statement. if it is "at home", then the corresponding element in vector "GetValue" will be TRUE.
forloop <- (1:49703)
for (i in forloop){
temp <- child_birth[i]
if (substr(temp, nchar(temp)-6, nchar(temp)) == "at home" ) {
GetValue[i] = TRUE
}
else{ GetValue[i] = FALSE }
}
I googled it to make sure that in R I don't need to do a predecalration before using a variable. but when I ran the code above, I got the error information:" Error: object 'GetValue' not found". So what's the problem with it?
Thank you!
GetValue[i] only makes sense if GetValue (and i) exist. Compare: x+i only makes sense if x and i exist, which has nothing to do with whether or not x and i must be declared before being used.
In this case, you need to define GetValue before the loop. I recommend
GetValue <- logical(length(child_birth))
so as to allocate enough space. In this case, you could drop the else clause completely since the default logical value is FALSE.
I also recommend dropping the variable forloop and using
for(i in seq_along(child_birth))
Why hard-wire in the magic number 49703? Such numbers are subject to change. If you put them explicitly in the code, you are setting yourself up for future bugs.

return value of if statement in r

So, I'm brushing up on how to work with data frames in R and I came across this little bit of code from https://cloud.r-project.org/web/packages/data.table/vignettes/datatable-intro.html:
input <- if (file.exists("flights14.csv")) {
"flights14.csv"
} else {
"https://raw.githubusercontent.com/Rdatatable/data.table/master/vignettes/flights14.csv"
}
Apparently, this assigns the strings (character vectors?) in the if and else statements to input based on the conditional. How is this working? It seems like magic. I am hoping to find somewhere in the official R documentation that explains this.
From other languages I would have just done:
if (file.exists("flights14.csv")) {
input <- "flights14.csv"
} else {
input <- "https://raw.githubusercontent.com/Rdatatable/data.table/master/vignettes/flights14.csv"
}
or in R there is ifelse which also seems designed to do exactly this, but somehow that first example also works. I can memorize that this works but I'm wondering if I'm missing the opportunity to understand the bigger picture about how R works.
From the documentation on the ?Control help page under "Value"
if returns the value of the expression evaluated, or NULL invisibly if none was (which may happen if there is no else).
So the if statement is kind of like a function that returns a value. The value that's returned is the result of either evaulating the if or the then block. When you have a block in R (code between {}), the brackets are also like a function that just return the value of the last expression evaluated in the block. And a string literal is a valid expression that returns itself
So these are the same
x <- "hello"
x <- {"hello"}
x <- {"dropped"; "hello"}
x <- if(TRUE) {"hello"}
x <- if(TRUE) {"dropped"; "hello"}
x <- if(TRUE) {"hello"} else {"dropped"}
And you only really need blocks {} with if/else statements when you have more than one expression to run or when spanning multiple lines. So you could also do
x <- if(TRUE) "hello" else "dropped"
x <- if(FALSE) "dropped" else "hello"
These all store "hello" in x
You are not really missing anything about the "big picture" in R. The R if function is atypical compared both to other languages as well as to R's typical behavior. Unlike most functions in R which do require assignment of their output to a "symbol", i.e a proper R name, if allows assignments that occur within its consequent or alternative code blocks to occur within the global environment. Most functions would return only the final evaluation, while anything else that occurred inside the function body would be garbage collected.
The other common atypical function is for. R for-loops only
retain these interior assignments and always return NULL. The R Language Definition calls these atypical R functions "control structures". See section 3.3. On my machine (and I suspect most Linux boxes) that document is installed at: http://127.0.0.1:10731/help/doc/manual/R-lang.html#Control-structures. If you are on another OS then there is probably a pulldown Help menu in your IDE that will have a pointer to it. Thew help document calls them "control flow constructs" and the help page is at ?Control. Note that it is necessary to quote these terms when you wnat to access that help page using one of those names since they are "reserved words". So you would need ?'if' rather than typing ?if. The other reserved words are described in the ?Reserved page.
?Control
?'if' ; ?'for'
?Reserved
# When you just type:
?if # and hit <return>
# you will see a "+"-sign which indicateds an incomplete expression.
# you nthen need to hit <escape> to get back to a regular R interaction.
In R, functions don't need explicit return. If not specified the last line of the function is automatically returned. Consider this example :
a <- 5
b <- 1
result <- if(a == 5) {
a <- a + 1
b <- b + 1
a
} else {b}
result
#[1] 6
The last line in if block was saved in result. Similarly, in your case the string values are "returned" implicitly.

R: Enriched debugging for linear code chains

I am trying to figure out if it is possible, with a sane amount of programming, to create a certain debugging function by using R's metaprogramming features.
Suppose I have a block of code, such that each line uses as all or part of its input the output from thee line before -- the sort of code you might build with pipes (though no pipe is used here).
{
f1(args1) -> out1
f2(out1, args2) -> out2
f3(out2, args3) -> out3
...
fn(out<n-1>, args<n>) -> out<n>
}
Where for example it might be that:
f1 <- function(first_arg, second_arg, ...){my_body_code},
and you call f1 in the block as:
f1(second_arg = 1:5, list(a1 ="A", a2 =1), abc = letters[1:3], fav = foo_foo)
where foo_foo is an object defined in the calling environment of f1.
I would like a function I could wrap around my block that would, for each line of code, create an entry in a list. Each entry would be named (line1, line2) and each line entry would have a sub-entry for each argument and for the function output. the argument entries would consist, first, of the name of the formal, to which the actual argument is matched, second, the expression or name supplied to that argument if there is one (and a placeholder if the argument is just a constant), and third, the value of that expression as if it were immediately forced on entry into the function. (I'd rather have the value as of the moment the promise is first kept, but that seems to me like a much harder problem, and the two values will most often be the same).
All the arguments assigned to the ... (if any) would go in a dots = list() sublist, with entries named if they have names and appropriately labeled (..1, ..2, etc.) if they are assigned positionally. The last element of each line sublist would be the name of the output and its value.
The point of this is to create a fairly complete record of the operation of the block of code. I think of this as analogous to an elaborated version of purrr::safely that is not confined to iteration and keeps a more detailed record of each step, and indeed if a function exits with an error you would want the error message in the list entry as well as as much of the matched arguments as could be had before the error was produced.
It seems to me like this would be very useful in debugging linear code like this. This lets you do things that are difficult using just the RStudio debugger. For instance, it lets you trace code backwards. I may not know that the value in out2 is incorrect until after I have seen some later output. Single-stepping does not keep intermediate values unless you insert a bunch of extra code to do so. In addition, this keeps the information you need to track down matching errors that occur before promises are even created. By the time you see output that results from such errors via single-stepping, the matching information has likely evaporated.
I have actually written code that takes a piped function and eliminates the pipes to put it in this format, just using text manipulation. (Indeed, it was John Mount's "Bizarro pipe" that got me thinking of this). And if I, or we, or you, can figure out how to do this, I would hope to make a serious run on a second version where each function calls the next, supplying it with arguments internally rather than externally -- like a traceback where you get the passed argument values as well as the function name and and formals. Other languages have debugging environments like that (e.g. GDB), and I've been wishing for one for R for at least five years, maybe 10, and this seems like a step toward it.
Just issue the trace shown for each function that you want to trace.
f <- function(x, y) {
z <- x + y
z
}
trace(f, exit = quote(print(returnValue())))
f(1,2)
giving the following which shows the function name, the input and output. (The last 3 is from the function itself.)
Tracing f(1, 2) on exit
[1] 3
[1] 3

T test failed in R

Iam using R to run a large number using input from a delimited table which is compost of 40000 row and 4 col. iam trying to implement the t test ,p value , but i have error which is (the data are essentially constant) , i used the for loop and apply for both case i had same issue the code is:
NormData3= NormData1[1:40000,1:5]
for(i in 1:nrow(NormData3)) {
g1=NormData3[i,2:3]
g2=NormData3[i,4:5]
p[i]=t.test(g1,g2,var.equal=TRUE)$p.value
}
I don't know what is the problem ??
It's nice that the software recognizes situations in which a sensible
answer can't be computed. At that point, there are two possible actions:
(1) stop with an informative error, and (2) silently return NA.
If you are running this in a iterative loop, you want the second output. Here is the small function for that :
my.t.test.p.value <- function(...) {
obj<-try(t.test(...), silent=TRUE)
if (is(obj, "try-error")) return(NA) else return(obj$p.value)
}
Use this function instead of t.test in your code. This will not disturb your loop and allows it to continue.

How can I determine if try returned an error or not?

I am trying to do the following:
try(htmlParse(ip[1], T),
where I define a as:
ip[1] = paste('http://en.wikipedia.org/wiki/George_Clooney')
I want to check if the htmlParse worked or not. For many names in my list, there will be no wikipedia sites and thus I need to be able to check and replace ip[1] with NA if the wiki pages does not exist.
Can someone please advise how I can do that. I tried using the command geterrmessage(), however I am not sure how to flush that everytime I change the name of the celebrity.
Currently I have the following:
if(!isTRUE(as.logical(grep(ip[1],err)))) {
ip[1] = NA
}
else {
This is definately incorrect as it is not running the logical statement I want.
Thanks
Amar
This simple example should help you out, I think:
res <- try(log("a"),silent = TRUE)
class(res) == "try-error"
[1] TRUE
The basic idea is the try returns (invisibly) an object of class "try-error" when there's an error. Otherwise, res will contain the result of the expression you pass to try. i.e.
res <- try(log(2),silent = TRUE)
res
[1] 0.6931472
Spend some time reading ?try carefully, including the examples (which aren't as simple as they could be, I guess). As GSee notes below, a more idiomatic way to check if an error is thrown is to use inherits(res,'try-error').
I would try to download all the names (existing or not) from wiki and save it in separate files.I would then grep the following string Wikipedia does not have an article with this exact name and for the non-existing ones I would get a TRUE value. In this way I believe you'll make sure whether the parser worked or the name didn't exist. Additionally you can sort the downloaded files based on their size in case you are suspecting that something went wrong. Corrupted ones have smaller size.
Additionally I would use tryCatch function in order to treat the logical status:
x<-3
tryCatch(x>5,error=print("this is an error"))
Here's a function that evaluates an expression and returns TRUE if it works and FALSE if it doesn't. You can also assign variables inside the expression.
try_catch <- function(exprs) {!inherits(try(eval(exprs)), "try-error")}
try_catch(out <- log("a")) # returns FALSE
out # Error: object 'out' not found
try_catch(out <- log(1)) # returns TRUE
out # out = 0

Resources