This question already has answers here:
Vectorized IF statement in R?
(6 answers)
Closed 6 years ago.
If I want to code a math function:
f(x)
= 12 for x>1
= x^2 otherwise
If I use
mathfn<-function(x)
{
if(x>1)
{
return(12)
}
else
{
return(x^2)
}
}
then I suppose that's not a good way to code it because it's not generic for calls in which x is a vector. e.g. plot() or integrate() fail.
plot(mathfn, 0,12)
Warning message:
In if (x > 1) { :
the condition has length > 1 and only the first element will be used
What's a more robust, vectorized idiom to code this so that x can either be a scalar or a vector?
Would something like this work:
mathfn <- function(x) ifelse(x > 1, 12, x^2)
Related
converter2 <- function(odds){
if(grepl("/", odds) == T){
x <- str_split(odds, "/")
y <- as.numeric(x[[1]][1])
z <- as.numeric(x[[1]][2])
a <- (1 / ((y/z) + 1)) * 100
return(a)
}
else{
x <- as.numeric(odds)
x <- 1/(x + 1)
return(x*100)
}
}
This is the code I have been using to create a function that converts a single character fractional odds to a percentage (e.g. if you write "7/2" it will return 22.222, but it doesn't work on a vector, returning the error:
1: In if (grepl("/", odds) == T) { :
the condition has length > 1 and only the first element will be used
Does anyone have a good way to fix this? I was thinking of using an ifelse statement but can't figure out what will work. Thanks.
I have been out of touch with R so bear with me.
sapply(vector, converter2)
This would apply the function on every element and return a vector.
Another option is
Vectorize(converter2)(c("7/22","3/7"))
I need to write an algorithm that gives you any number n in base 3 in R.
So far I wrote that:
NameOfTheFunction <- function(n) { while (n != 0) {
{q<- n%/%3}
{r <- n%%3}
{return(r)}
q<- n } }
My problem is that I now need to stock every r in a vector. I've never done that and don't quite know how to handle it. I tried to find some things on the internet but I did not find anything really relevant to this particular situation.
After your function, use:
sapply(vector, FUN=function(n) return(NameOfTheFunction(n)))
What sapply does is, for a given vector of your choice, it will repeat the function NameOfTheFunction(n) using every element in your vector in place of n in the function. The result, in this case, will be a vector of every output from your vector.
For example:
vector <- c(10, 100, 1000, 10000)
NameOfTheFunction <- function(n) { while (n != 0) {
{q<- n%/%3}
{r <- n%%3}
{return(r)}
q<- n } }
sapply(vector, NameOfTheFunction)
[1] 1 1 1 1
This question already has answers here:
Returning anonymous functions from lapply - what is going wrong?
(2 answers)
Closed 8 years ago.
I have the following R Code (the last part of this question), after the last line I expect to get a list of 4 "retFun" functions, each initialized with a different x so that I get the following result
funList[[1]](1) == 7 #TRUE
funList[[2]](1) == 8 #TRUE
And so on, but what I seem to get is
funList[[1]](1) == 10 #TRUE
funList[[2]](1) == 10 #TRUE
As if each function in the list has the same x value
creatFun <- function(x, y)
{
retFun <- function(z)
{
z + x + y
}
}
myL <- c(1,2,3,4)
funList <-sapply(myL, creatFun, y = 5)
This could be (and probably is, somewhere) an exercise on how lazy evaluation works in R. You need to force the evaluation of x before the creation of each function:
creatFun <- function(x, y)
{
force(x)
retFun <- function(z)
{
z + x + y
}
}
...and to be safe, you should probably force(y) as well for the times when you aren't passing a single value in for that parameter.
A good discussion can be found in Hadley's forthcoming book, particularly the section on lazy evaluation in the Functions chapter (scroll down).
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to write an R function that evaluates an expression within a data-frame
I want to write a function that sorts a data.frame -- instead of using the cumbersome order(). Given something like
> x=data.frame(a=c(5,6,7),b=c(3,5,1))
> x
a b
1 5 3
2 6 5
3 7 1
I want to say something like:
sort.df(x,b)
So here's my function:
sort.df <- function(df, ...) {
with(df, df[order(...),])
}
I was really proud of this. Given R's lazy evaluation, I figured that the ... parameter would only be evaluated when needed -- and by that time it would be in scope, due to 'with'.
If I run the 'with' line directly, it works. But the function doesn't.
> with(x,x[order(b),])
a b
3 7 1
1 5 3
2 6 5
> sort.df(x,b)
Error in order(...) : object 'b' not found
What's wrong and how to fix it? I see this sort of "magic" frequently in packages like plyr, for example. What's the trick?
This will do what you want:
sort.df <- function(df, ...) {
dots <- as.list(substitute(list(...)))[-1]
ord <- with(df, do.call(order, dots))
df[ord,]
}
## Try it out
x <- data.frame(a=1:10, b=rep(1:2, length=10), c=rep(1:3, length=10))
sort.df(x, b, c)
And so will this:
sort.df2 <- function(df, ...) {
cl <- substitute(list(...))
cl[[1]] <- as.symbol("order")
df[eval(cl, envir=df),]
}
sort.df2(x, b, c)
It's because when you're passing b you're actually not passing an object. Put a browser inside your function and you'll see what I mean. I stole this from some Internet robot somewhere:
x=data.frame(a=c(5,6,7),b=c(3,5,1))
sort.df <- function(df, ..., drop = TRUE){
ord <- eval(substitute(order(...)), envir = df, enclos = parent.frame())
return(df[ord, , drop = drop])
}
sort.df(x, b)
will work.
So will if you're looking for a nice way to do this in an applied sense:
library(taRifx)
sort(x, f=~b)
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to check if each element in a vector is integer or not in R?
How to make a function that checks whether a number is a whole number (such as -3, 2.0, 0,3, and 4.0000, but not 3.3, or 2.001)
Try typing in R:
?is.integer
You will go to this page:
R is.integer() page
At the bottom is a function that I believe you want:
is.wholenumber <-
function(x, tol = .Machine$double.eps^0.5) abs(x - round(x)) < tol
is.wholenumber(1) # is TRUE
(x <- seq(1,5, by=0.5) )
is.wholenumber( x ) #--> TRUE FALSE TRUE ...