iferror equivalent in R - r

Here is the simplified version:
Suppose I am using 'which' function to find a position, say -
position_num=which(df$word=="ABC")
If the value exists it is fine and it returns an integer, but in case it is unable to match it returns integer(0) in such a case I want to assign a default value to position_num=1.
Thanks for the help in advance

Something like the following if() statement would probably do it.
position_num = if(!length(w <- which(df$word == "ABC"))) 1 else w
Here we are just checking to see if the result from which() has a length, because
length(integer(0))
# [1] 0
And we return 1 if it doesn't have a length, and the which() result (w) otherwise.

Would this work for you?
position_num=ifelse(length(which(df$word=="ABC")) != 0,which(df$word=="ABC"),1)

Related

Using R, can I create special functions like %in% just one input (LEFT) or (RIGHT)?

The common notation for factorial is the ! operator in mathematics.
I can create function:
"%!%" = function(n, r=NULL) { factorial(n); }
This works as expected if I pass a NULL or NA to the RHS, which I don't really want to do.
3 %!% NA
3 %!% NULL
3 %!% .
What I would like to do is just enter:
3 %!%
Any suggestions on HOW I can do that? In that setup, I want the LHS (left) to be the input and the RHS (right) to be ignored.
I can do the BOTH no problem:
nPr = function(n, r, replace=FALSE)
{
if(replace) { return( n^r ); }
factorial(n) / factorial(n-r);
}
"%npr%" = "%nPr%" = nPr;
nCr = function(n, r, replace=FALSE)
{
# same function (FALSE, with n+r-1)
if(replace) { return( nCr( (n+r-1), r, replace=FALSE ) ); }
factorial(n) / ( factorial(r) * factorial(n-r) );
}
"%ncr%" = "%nCr%" = nCr;
where
5 %nCr% 3
5 %nPr% 3
work as expected based on selection without replacement.
Question: How to use the special operator with just the LHS?
The follow-on question is the opposite. Let's say I want the LHS (left) to be ignored and focus on the RHS (right). I believe this is how the built-in ? function links to help and ?? links to help.search(). Let's say I wanted to create an %$$% operator that worked that way.
No, you can't do that. The %any% operators are defined by the parser to be binary operators.
You can see all of the operators in R in the ?Syntax help page. Some are binary, some are unary, and some can be either one, but the unary operators always precede the argument. You can attach different functions to most of them (e.g. change the meaning of ! in !x), but you can't change the parser to allow x! to be legal code.

R function length error message

I made a function to to compute the sum of I(Xi
my.ecdf<- function(x,y) {
if(!is.null(dim(y)))
stop("y has more than one dimension")
n<-length(x)
i<-1:n
p<-if(x[i]<y) 1 else {
0
}
(sum(p))/n
}
But when I run it with input (rnorm(11),6), I get this error:
Warning message:
In if (x[i] < y) 1 else { :
the condition has length > 1 and only the first element will be used
Any ideas? I'm new to r so sorry if it's something obvious. (Also I don't want to use the for loop)
There are a number of issues in your code:
1) Whats the point of x[1:length(x)] in the if statement? Right now these are meaningless and can be dropped:
n<-length(x)
i<-1:n
x[i]
2) If statement accepts a logical argument not a vector of logical, you can consider adding all() any() etc like
if(all(x < y)) 1 else {0}
or use ifelse() statement for the assignment
3) Finally from what I can understand you overcomplicate things and the whole thing can be written as one-liner:
sum(x < y)/length(x)
This is a logical vector of the same length as y
is.null(dim(y))
You're using it as a logical test. An object with a length greater than 1 can't be unambiguously interpreted by the if statement. Consider if (TRUE FALSE FALSE TRUE) <do something>. When should you do that thing?
If you want to make sure y doesn't have more than one dimension, do
if(length(dim(y)) > 1){
stop("message")
}

If else statement doesnt work and cant figure out why

Can someone explain why my else part of my function doesnt work?
finaltable;
Duplicate Digit6 Digit7 Digit7a Digit7b Digit7c Digit7d Dead carried
137401 137401 2017681 2017681 2018047 2018047 2018219 1 0
137402 137402 2017731 2017731 2017856 2017856 2018279 0 0
w <- function(finaltable){
if (nchar(tail(names(finaltable),1) >= nchar(c("carried")))) {(ncol(finaltable)-2)
} else (ncol(finaltable)-1)
}
I have colnames (Duplicate, digit, dead, carried). I want the last digit column. Depending on the day I will have tail(names(finaltable),1 = carried or dead. If carried, I need to subtract two columns, if dead then one column. However, I have several columns named dead or carried that are associated with number. However, the max dead will be is dead99. Thus I have a max of 6 characters.
I then want to dump my function into below.
SubtractROW<-finaltable[paste(ROWS), w(finaltable)];
BarCODEtable<-cbind(ILS,ROWS,SubtractROW);
BarCODEtable;
Here's your function, corrected so that it returns the right values:
w <- function(finaltable){
if (nchar(tail(names(finaltable),1)) >= nchar("carried")) {
(ncol(finaltable)-2)
} else {
ncol(finaltable)-1
}
}
w(finaltable) # if last column is dropped
#[1] 7
The problem was in your if statement, where a ) was at the wrong place. Running your original if statement results in:
nchar(tail(names(finaltable),1) >= nchar(c("carried")))
#[1] 4
where it should be
nchar(tail(names(finaltable),1)) >= nchar("carried")
#[1] FALSE
But as commented above, you could more easily use
max(which(grepl("^Digit", names(finaltable))))
instead.

Stuck in an infinite loop in a function

I'm stuck in an infinite loop in this function:
let rec showGoatDoorSupport(userChoice, otherGuess, aGame) =
if( (userChoice != otherGuess) && (List.nth aGame otherGuess == "goat") ) then otherGuess
else showGoatDoorSupport(userChoice, (Random.int 3), aGame);;
And here's how I'm calling the function:
showGoatDoorSupport(1, 2, ["goat"; "goat"; "car"]);
In the first condition in the function, I compare the first 2 input parameters (1 and 2) if the are different, and if the item in the list at index "otherGuess" is not equal to "goat", I want to return that otherGuess.
Otherwise, I want to run the function again with a random number between 0-2 as the second input parameter.
The point is to keep trying to run the function until the second parameter doesnt equal the first, and that slot in the List isn't "goat", then return that slot number.
Don't use ==, it checks for physical equality. Use =. Two different strings will never be physically equal, even if they contain the same sequence of characters. (This is necessary, because strings are mutable in OCaml.)
$ ocaml
OCaml version 4.00.0
# "abc" == "abc";;
- : bool = false
# "abc" = "abc";;
- : bool = true
Another to do that is to use the String.compare. An example:
if String.compare str1 str2 = 0 then (* case equal *)
else (* case not equal *)

Solve equation, strange result

here is my code to solve equation:
fx=function(x){ x^3-x-3}
solve=function(a,b,eps){
if(abs(fx(a))<0.00001) return(list(root=a,fun=fx(a)))
else if(abs(fx(b))<0.00001) return(list(root=b,fun=fx(b)))
else if (fx(a)*fx(b)>0) return(list(root="failed to find"))
if (a>b){
c<-a
a<-b
a<-b}
while( b-a>eps ){
x=(a+b)/2
if (fx(x)==0) {return(list(root=x,fun=fx(x))) }
else if (fx(a)*fx(x)<0) {b=x }
else {a=x}}
myroot=(a+b)/2
return(list(root=myroot,value=fx(myroot)))
}
> solve(1,3,1e-8)
$root
[1] 1.6717
$value
[1] 2.674228e-08
> fx(1.6717)
[1] 8.73813e-07
Why fx(1.6717) != $value, I want to know the reason
8.73813e-07!=2.674228e-08?
how can i revise:return(list(root=myroot,value=fx(myroot)))
to make my root more digits ?
When R prints a value, it uses by default digits=3, i.e. printing 3 significant digits. This means you made an error of interpretation when looking at your results.
Try this:
x <- solve(1,3,1e-8)
print(x[[1]], digits=9)
[1] 1.67169989
Now substitute the actual returned value into your function:
fx(x[[1]])
[1] 2.674228e-08
Now the values match.
In summary, you have made a rounding error when interpreting the printed results of your function.
You can trace this behaviour in the R help files as follows:
?print
will point you to
?print.default
Which has this to say about the digits argument:
digits: a non-null value for digits specifies the minimum number of significant digits to be printed in values. The default, NULL, uses getOption(digits). (For the interpretation for complex numbers see signif.) Non-integer values will be rounded down, and only values greater than or equal to 1 and no greater than 22 are accepted.
Try this and look at the print() of a and b.
fx=function(x){ x^3-x-3}
solve=function(a,b,eps){
if(abs(fx(a))<0.00001) return(list(root=a,fun=fx(a)))
else if(abs(fx(b))<0.00001) return(list(root=b,fun=fx(b)))
else if (fx(a)*fx(b)>0) return(list(root="failed to find"))
if (a>b){
c<-a
a<-b
a<-b}
while( b-a>eps ){
x=(a+b)/2
if (fx(x)==0) {return(list(root=x,fun=fx(x))) }
else if (fx(a)*fx(x)<0) {b=x }
else {a=x}}
myroot=(a+b)/2
print(a,digits=20)
print(b,digits=20)
return(list(root=myroot,value=fx(myroot)))
}
There is a round.

Resources