Vectorized arguments in function - r

I have created the following function in R:
f<-function(t) {
if (t<0){
f<-0
return(f)
} else {
f<-(2*t)/((1+t^2)^2)
return(f)
}
}
The function works fine, but when I try to operate with it or plot it, I get the following error:
In if (t < 0) { :
the condition has length > 1 and only the first element will be used
I have tried to use if-else, as some other post suggested, but I cannot get any improvement.
What can I do to fix it?

Related

How to write R function

My attempt is below- I don't know how to create my function in a way where my first element will be π and my second element lambda. Any help would be great.
F<- function(y){ exp(-y)/(sqrt(2*pi*y))}
prob<-function(y, lambda)
{(lambda^y) / (F(y)*1-exp(-lambda))}
If I understood correctly You are missing if/else in your function.
prob<-function(y, lambda)
{ if(y==0)
{
return(pi)
} else {
return((lambda^y) / (F(y)*1-exp(-lambda)))
}
}
When y is equal 0 it returns pi otherwise formula you wrote

Nargin function in R (number of function inputs)

Goal
I am trying to create a function in R to replicate the functionality of a homonymous MATLAB function which returns the number of arguments that were passed to a function.
Example
Consider the function below:
addme <- function(a, b) {
if (nargin() == 2) {
c <- a + b
} else if (nargin() == 1) {
c <- a + a
} else {
c <- 0
}
return(c)
}
Once the user runs addme(), I want nargin() to basically look at how many parameters were passed―2 (a and b), only 1 (a) or none―and calculate c accordingly.
What I have tried
After spending a lot of time messing around with environments, this is the closest I ever got to a working solution:
nargin <- function() {
length(as.list(match.call(envir = parent.env(environment()))))
}
The problem with this function is that it always returns 0, and the reason why is that I think it's looking at its own environment instead of its parent's (in spite of my attempt of throwing in a parent.env there).
I know I can use missing() and args() inside addme() to achieve the same functionality, but I'll be needing this quite a few other times throughout my project, so wrapping it in a function is definitely something I should try to do.
Question
How can I get nargin() to return the number of arguments that were passed to its parent function?
You could use
nargin <- function() {
if(sys.nframe()<2) stop("must be called from inside a function")
length(as.list(sys.call(-1)))-1
}
Basically you just use sys.call(-1) to go up the call stack to the calling function and get it's call and then count the number of elements and subtract one for the function name itself.

Creating R function questions

We have difficulty in writing a function in the R program.Our question is:
"If the number we have is odd, let's multiply by 3 and increase by 1. If our number is even, let's divide by two.
EXAMPLE
if our number is 7,
7*3+1=22
22/2=11
11*3+1=34
34/2=17
....
So that the series continues" could you please help us?
f=function(x) {
if(which(x%%2==0)) {
x=x/2
print(x)
} else {
if(which(x%%2==1)) {
x=3*x+1
print(x)
}
}
}
> f(2)
[1] 1
> f(4)
[1] 2
> f(3)
Error in if (which(x%%2 == 0)) { : argument is of length zero
You can vastly simplify this code. I think others have already mentioned that "which" is not correct here. But also look at the fact that if something is not even (divisible by two) then it must be odd. This implies that the decision is dichotomous (i.e. 0 or 1). You can therefore simplify the code to the following. Notice that we have also move the print after the if statement since we must always print the result. It isn't necessary to duplicate the code. As for the series you will need to use a loop. You could look at running a recursive loop, but keep in mind that this is a never ending function and you should stop it unless you'd like to make an attempt at seeing infinity.
f=function(x) {
if(x%%2==0) {
x=x/2
} else {
x=3*x+1
}
return (x) # Ben Bolker made a good point that you will need to return X
}
f(1)
f(2)
f(7)

Foreach does not perform IF statements

I've implemented foreach in one of the multiple for statements of my R code. It returns the main result (the one after all the iterations), however, it does not perform an IF statement within the code.
Below the skeleton of my code (it's too long to put everything).The if statement does not work and variable "Disc_Time" remains the same (as initialized). What I'm doing wrong or missing? I've tried with .export="f" and .export=ls(GlovalEnv) without success.
library(foreach)
library(doParallel)
cores=detectCores()
cl <- makeCluster(cores[1]-1) #not to overload your computer
registerDoParallel(cl)
Disc_Time<-c("UE","Beam_order","Time")
.... MORE VARIABLES
MDP_x<-foreach (d = 1:length(dista),.combine='c')%dopar%
{
for (q in 1:sim)
{
for (ue in 1:n)
{
for (i in 1:length(seq_order_BS))
{
for (j in 1:length(seq_order_UE))
{
if(first==0)
{
Disc_Time<-rbind(Disc_Time,c(ue,i,D_Time))
}
}
}
}
}
stopcluster(cl)
To see if your if statement is working, we need to know how first is set, and what value it has before your loop. It does not look like first changes within your loop anyway, so it really should sit outside your %dopar% statement anyway.
That said, the if statement is not your issue. foreach returns a list of each return of the expression within. For example:
ls <- foreach(d = 1:5) %dopar% {
return(i)
}
gives an list ls that contains the numbers one to five.
The only expression in your function is an assignment call to Disc_Time. This is evaluated within each of your nodes, and never returned to the parent environment. Disc_Time is never changed where the code was called from).
It looks as though you are trying to set a side effect of your parallel function (to change Disc_Time), which to my knowledge is not possible in a parallel context. Perhaps you want:
MDP_x<-foreach (d = 1:length(dista),.combine='c')%dopar%
{
for (q in 1:sim)
{
for (ue in 1:n)
{
for (i in 1:length(seq_order_BS))
{
for (j in 1:length(seq_order_UE))
{
if(first==0)
{
return(rbind(Disc_Time,c(ue,i,D_Time)))
} else {
return(NA)
}
}
}
}
}
stopcluster(cl)
MDP_x should then have the values you want for each d

R - Writing a function to return binary output using if statement

Good day,
I am a beginner and trying to understand why I am getting the error below.
I am trying to create a function that would return 0 or 1 based on column values in data set.
LT = function(Lost.time) {
For (i in 1:dim(df)) {
if (df$Lost.time > 0) {
x = 1
}
else {
x = 0
}
return(x)
}
}
Error: no function to return from, jumping to top level In addition: Warning
message: In if (df$Lost.time > 0) { : the condition has length > 1 and only
the first element will be used> } Error: unexpected '}' in "}"
There are a couple of mistakes in the code:
R is case sensitive. Use for instead of For.
If you are looping over the entries in df$Lost.time, the individual elements should be addressed within the loop using df$Lost.time[i]. However, a loop is not necessary for this task.
An else statement should not begin on a new line of the code. The parser cannot know that the if statement is not finished after the first block. If the else statement is enclosed in curly braces like in } else { there will be no problem in this sense.
The parameter passed to the function is not suitable. Maybe you could pass df, instead of Lost.time, but it may be necessary to rewrite parts of the function.
The use of 1:dim(df) in the for loop should work, but it will trigger a warning message. It is better to use 1:nrow(df).
Those are syntax problems. However, the main issue is probably what has been addressed in the answer by #TimBiegeleisen: In the loop you are checking for each of the ̀nrow(df) elements of df$Lost.time whether a specific condition is fulfilled. It therefore does not seem to make sense to have a single binary result as return value. The purpose of the function should be clarified before it is implemented.
An alternative to this function could be constructed in a one-liner with ifelse.
It is not clear what you actually want to return in your function. return can only be called once, after which it will return a single value and the function will terminate.
If you want to get a vector which will contain 1 or 0 depending on whether a given row in your data frame has Lost.time > 0, then the following one liner should do the trick:
x <- as.numeric(df$Lost.time > 0)
If loops are used for writing a function indices should be used for each element.
Create a variable(x) in your dataframe, if the statements goes true it prints 1 else 0
LT = function(Lost.time) {
for (i in 1:dim(df)) {
if (as.numeric(df$Lost.time[i]) > 0) {
df$x[i] <- 1
}else{
df$x[i] <- 0
}
}
}

Resources