using ifelse in r with multiple returns - r

I was wondering how to set two or more results from a true ifelse statement.
For example, I would like to set y = 2 and t=3 if x=2. I was thinking the code would look something like this:
x=2
ifelse(x==2,y=2 & t=3, y=0 & t=0)
however this does not work.

You may use if-statement block:
if(x == 2){
y = 2
t = 3
}
else {
y = 0
t = 0
}
Alternatively, you can try:
ifelse(x == 2, {y = 2; t = 3;}, {y = 0; t = 0;})

As answered here: If statement with multiple actions in R, for the block IF statement, the ELSE should be on the same line as the previous curly bracket.
So, instead of
if(x ==2) {
y = 2
t = 3
}
else {
y = 0
t = 0
}
the format should be (the ELSE is on the same line as the previous curly bracket)
if(x ==2) {
y = 2
t = 3
} else {
y = 0
t = 0
}

Related

If-Statements and integrate() function in R

Do if statements not work for integrate? I have to do something much more complicated than this, but I am supplying this example because it isolated the problem.
Kernel = function(x){
if(abs(x)<1){
w = 1 - abs(x)
} else{
w = 0
}
return(w)
}
integrate(Kernel,
0,
1)
The error message:
the condition has length > 1 and only the first element will be used
Kernel = function(x){
pmax(1-abs(x), 0)
}
integrate(Kernel, 0, 1)
0.5 with absolute error < 5.6e-15
or even:
Kernel1 = function(x){
ifelse(abs(x)<1, 1-abs(x), 0)
}
integrate(Kernel1, 0, 1)
0.5 with absolute error < 5.6e-15
If you want to maintain the way you have written your function, you have to vectorize it:
Kernel2 = function(x){
ifelse(abs(x)< 1, 1-abs(x), 0)
if(abs(x)<1){
w = 1 - abs(x)
} else{
w = 0
}
return(w)
}
integrate(Vectorize(Kernel2), 0, 1)
0.5 with absolute error < 5.6e-15

While Loop Inside For Loop in r

I expect the given code to output the answer : 1. However the loop runs forever. I am trying to see if while loop works for such a case. The use of while loop is necessary for the solution.
a = list(1,2,3,4)
for(i in a){
while(i != 2){
print(i)
}
}
Here are two solutions that work with while. The first one with a 'flag' set as TRUE, and the index as 1, based on the condition, set the 'flag' to FALSE
flag <- TRUE
i <- 1
while(flag) {
print(a[[i]])
i <- i + 1
if(a[[i]] == 2) {
flag <- FALSE
}
}
#[1] 1
Or we add a break
i <- 1
while(TRUE) {
print(a[[i]])
i <- i + 1
if(a[[i]] == 2) {
break
}
}
#[1] 1
The value of i does not change inside the while loop, so you never advance to the next item in list. You need if instead of while:
a = list(1,2,3,4)
for(i in a){
if(i != 2){
print(i)
}
}

implement matrix determinant in R

I was asked to implement function that calculates n-dimensional matrix determinant using Laplace expansion. This involves recursion. I developed this:
minor<-function(A,i,j) {
return(A[c(1:(i-1),(i+1):dim(A)[1]),c(1:(j-1),(j+1):dim(A)[2])])
}
determinantRec<-function(X,k) {
if (dim(X)[1] == 1 && dim(X)[2] == 1) return(X[1][1])
else {
s = 0
for (i in 1:dim(X)[2]) {
s = s + X[k][i]*(-1)^(k+i)*determinantRec(minor(X,k,i),k)
}
return(s)
}
}
where k in determinantRec(X,k) function indicates which row I want to use Laplace expansion along of.
My problem is when I run determinantRec(matrix(c(1,2,3,4),nrow = 2,ncol = 2),1) this error appears:
C stack usage 7970628 is too close to the limit
What is wrong with my code?
#julia, there is one simple type in your code. Just remove the '*' at the end of the definition of 's'. And don't indent the recursion.
determinantRek<-function(X,k) {
if (dim(X)[1] == 1 && dim(X)[2] == 1)
return(X[1,1])
if (dim(X)[1] == 2 && dim(X)[2] == 2)
return(X[1,1]*X[2,2]-X[1,2]*X[2,1])
else
s = 0
for (i in 1:dim(X)[2]) {
s = s + X[k,i]*(-1)^(k+i)
determinantRek(X[-k,-i],k)
}
return(s)
}
I did this way and works just fine, although it is super slow, compared to the det function in base R
laplace_expansion <- function(mat){
det1 <- function(mat){
mat[1]*mat[4]-mat[2]*mat[3]
}
determinant <- 0
for(j in 1:ncol(mat)){
mat1 <- mat[-1,-j]
if(nrow(mat1) == 2){
determinant <- determinant+mat[1,j]*(-1)^(1+j)*det1(mat1)
}else{
val <- mat[1,j]*(-1)^(1+j)
if(val != 0){
determinant <- determinant+val*laplace_expansion(mat1)
}
}
}
return(determinant)
}
This is my approach, I think it's cleaner.
deter <- function(X) {
stopifnot(is.matrix(X))
stopifnot(identical(ncol(X), nrow(X)))
if (all(dim(X) == c(1, 1))) return(as.numeric(X))
i <- 1:nrow(X)
out <- purrr::map_dbl(i, function(i){
X[i, 1] * (-1)^(i + 1) * deter(X[-i, -1, drop = FALSE])
})
return(sum(out))
}
Thank you #ArtemSokolov and #MrFlick for pointing the problem cause, it was it. I also discovered that this code does not calculate properly the determinant of 2x2 matrix. After all it looks like that:
determinantRek<-function(X,k) {
if (dim(X)[1] == 1 && dim(X)[2] == 1)
return(X[1,1])
if (dim(X)[1] == 2 && dim(X)[2] == 2)
return(X[1,1]*X[2,2]-X[1,2]*X[2,1])
else
s = 0
for (i in 1:dim(X)[2]) {
s = s + X[k,i]*(-1)^(k+i)*
determinantRek(X[-k,-i],k)
}
return(s)
}
Debuging with browser() was also helpful :)

Why getting argument is of length zero` in R?

I have a simple function called PAP. I'm wondering when I run it why I get the following error:
Error in if (n.sim < 2) { : argument is of length zero
Here is my PAP function:
PAP = function (n.sim, sim.time){
n.sim = if(n.sim < 1) { n.sim = 1 } # If a user put zero or a negative number, make it 1
sim.time = if(n.sim < 2) { sim.time = 0 } else { sim.time }
for (i in 1:n.sim) {
plot( rnorm(1e2) )
Sys.sleep( sim.time ) }
}
PAP(n.sim = 2, sim.time = 5)
You shouldn't try to assign the results of an if statement, because this happens:
> n.sim = 2
> n.sim = if(n.sim < 1) { n.sim = 1 }
> n.sim
NULL
Instead you should do:
PAP = function (n.sim, sim.time){
if(n.sim < 1) {
n.sim = 1
} # If a user put zero or a negative number, make it 1
if(n.sim < 2) {
sim.time = 0
} # else didn't do anything here so removed
for (i in 1:n.sim) {
plot( rnorm(1e2) )
Sys.sleep( sim.time )
}
}
i.e. just use if as a control flow statement that determines whether particular lines get executed, and use the code within the if statement to change your variables.

MATLAB to R Conversion: Append values to an existing empty array through for loop

I have the below code with me. This code was written originally in MATLAB. I have two questions here:
1) What would be the corresponding command in R for the below command in MATLAB:
duet(i).p = [];
2) In the below code I am getting all the correct 6 values for duet$n, but I am not getting correct values for duet$p. My question is how to append the values to an empty existing array duet$p[i] in R through the for loop iterations.
This line is not working in the below code:
duet$p[i] <- c(duet$p[i],j)
I might also have declared duet$p[i] <- array() incorrectly.
The values for duet.n and duet.p from MATLAB are:
duet.n
2 0 2 0 1 3
duet.p
[] [3,6] [] [1,3,5,6] [1,6] []
In R, I am getting duet$n values correctly, but I am not able to get the array kind of results for duet$p.
Any help to get the duet$p values would be appreciated.
x <- matrix(c(-1,2,4,1,7,4.2,3,0,1.2,-1.2,5.1,4,2,3.1,1.1,1,1,9,0,1,2,2,8,1,2,2,2,2,2,2),nrow=6,ncol=5,byrow=T)
fro=1;N=6;M=2;V=3;
F <- list(f=c())
duet = list()
for (i = 1 : N){
duet$n[i] = 0
duet$p[i] = array() ## Create an empty array
for (j in 1 : N){
dl = 0
de = 0
dm = 0
for (k = 1 : M){
if (x[i,V + k] < x[j,V + k]){
dl = dl + 1
} else if (x[i,V + k] == x[j,V + k]){
de = de + 1
} else{
dm = dm + 1
}
}
if (dl == 0 & de != M){
duet$n[i] = duet$n[i] + 1
} else if (dm == 0 & de != M){
duet$p[i] = c(duet$p[i],j)
}
}
if (duet$n[i] == 0){
x[i,6] = 1
F$f = c(F$f,i)
}
}
This appears to get the output you want:
x <- matrix(c(-1,2,4,1,7,4.2,3,0,1.2,-1.2,5.1,4,2,3.1,1.1,1,1,9,0,1,2,2,8,1,2,2,2,2,2,2),nrow=6,ncol=5,byrow=T)
fro=1;N=6;M=2;V=3;
F <- list(f=c())
duet = list(n=rep(0,N), p=lapply(1:N, function(x)c()))
for (i in 1 : N){
duet$n[i] = 0
#duet$p[[i]] = c() ## Create an empty array
#if(i==2) browser()
for (j in 1 : N){
k=1:M
dl <- sum(x[i,V + k] < x[j,V + k])
de <- sum(x[i,V + k] == x[j,V + k])
dm <- sum(x[i,V + k] > x[j,V + k])
if (dl == 0 & de != M){
duet$n[i] = duet$n[i] + 1
} else if (dm == 0 & de != M){
duet$p[[i]] = c(duet$p[[i]],j)
}
}
if (duet$n[i] == 0){
#x[i,6] = 1
F$f = c(F$f,i)
}
}
What have I done?
commented out the line x[i,6] =1, because there isn't an x[i,6], and I'm not sure what you meant it to be. You will need to sort this out.
Initialised duet$n as a vector
Initialised duet$p as a list of n empty vectors
removed the k loop as conditional counting in R can be done as the sum of elements where the condition is TRUE.
corrected the syntax of for loops: = became in
I think you're trying to do duet[i]$p instead of what you're doing. Also you need to initialize each cell as a list

Resources