Foreach does not perform IF statements - r

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

Related

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.

Correcting unfinished function in R

I should correct unfinished function Rfun() but I haven't managed to find all of the problems.
Rfun(N){
A=matrix(0,nrow=50,ncol=300)
t=c(0:30,0:-30)
for(j in 1:50)
x=N[j,]
y=cumsum(x)
for(i in 1:300){
A[j,i]=y[i]/3
}
}
return(A)
}
Well since you didn't precise what the function should do, let me help you with what is apparently false to me:
This is not how you define a function in R you need to write Rfun = function(N){}.
The return(A) should be inside the function. Therefore you should remove one parenthesis.
the variable t is not used at all.

Vectorized arguments in function

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?

how can I terminate a call chain in r without using stop() or quit()?

Assume that in R there is a sequence of functions calling one another:
a = function() {...b()...}
b = function() {...c()...}
c = function() {...d()...}
and so on, where ... indicates omitted code. Now let's say that function d reaches a satisfactory state and wants to terminate the entire call chain and return to the Global Environment (assuming this is being run from within R GUI). Is there a way for function d to terminate the entire call chain? I realize stop() can achieve this, but stop() generates an error, which is not what I want. I also do not want to use quit() as I do not want to terminate the R GUI session.
ADDENDUM:
I also do not want to have to process a chain of return statements. This is because it is not necessarily the case that the calling functions will have knowledge of the called functions, which can be plugged in and unplugged, so to speak.
This is not really elegant but you could use a "break" variable that's living out of the the functions environments using <<-. Maybe something like that:
do_break <- FALSE
a = function(break = do_break) {
...
if(condition) {
do_break <<- TRUE
}
if(!do_break) {
b(do_break)
}
...
}
b = function(break = do_break) {
...
if(condition) {
do_break <<- TRUE
}
if(!do_break) {
c(do_break)
}
...
}
c = function(break = do_break) {
...
if(condition) {
do_break <<- TRUE
}
if(!do_break) {
d(do_break)
}
}

output from "for" loop

based on Roland's suggestion from Plot titles in R using sapply(), I have created the following loop to make boxplots out of every selected variable in my dataset.
all.box=function(x) {
for (i in seq_along(x)) {
boxplot(x[,i], main = names(x)[i])
}
}
It does the job nicely in that it provides the graphs. Could someone point out to me how to make the loop to return some output, say the $out from the boxplot to be able to see the number of outliers calculated by it?
Thanx a lot!
Using lapply here is better to avoid side-effect of the for:
all.box=function(x) {
res <- lapply(seq_along(x),function(i){
boxplot(x[,i], main = names(x)[i])$out
})
res
}
PS: you can continue to use for, but you will need either to append a list as a result within your loop or to allocate memory for the output object before calling boxplot. So I think it is simpler to use xxapply family function here.
If you want to return something from a for loop, it's very important to pre-allocate the return object if it's not a list. Otherwise for loops with many iterations will be slow. I suggest to read the R inferno and Circle 2 in particular.
all.box=function(x) {
result <- list()
for (i in seq_along(x)) {
result[[i]] <- boxplot(x[,i], main = names(x)[i])$out
}
result
}

Resources