Basically I wan to be able to save a function output in numeric format into an R object. The function contains a loop and ifelse arguments which may contribute to my difficulties in achieving this.
I would like to create a function like the following:
fnct <- function(x, y) {
for (i in x) {
ifelse(i >= y[1] & i <= y[2], y[3],
ifelse(i < y[1], y[1],
ifelse((max(x) - y[2] > y[1]), y[2],
NA)))
}
}
If I run this code, nothing happens.
fnct(c(1:150), c(20, 80, 50))
If I modify the code as follows by adding print arguments, I get an ouptut:
fnct <- function(x, y) {
for (i in x) {
ifelse(i >= y[1] & i <= y[2],
print(y[3]),
ifelse(i < y[1],
print(y[1]), ifelse((max(x) - y[2] > y[1]),
print(y[2]),
print(NA))))
}
}
But I cannot save it to an r object.
I have also tried the following:
fnct <- function(x, y) {
res <- matrix(nrow=length(x))
for (i in x) {
ifelse(i >= y[1] & i <= y[2],
res[i] <- (y[3]),
ifelse(i<y[1],
res[i] <- (y[1]), ifelse((max(x) - y[2] > y[1]),
res[i] <- (y[2]),
res[i] <- (NA))))
}
return(res)
}
which works in this case:
fnct(c(1:150), c(20, 80, 50))
but not for this:
fnct(seq(1.575, 5.125, by=0.05), c(1.5, 3, 3.5))
for
loop.You must create a vector where you save the ifelse
results.
Also, note that the question's last ifelse
does not depend on the index so it can be pre-computed.
fnct <- function(x,y) {
out <- numeric(length(x))
pre_comp <- ifelse(max(x) - y[2] > y[1], y[2], NA)
for (i in seq_along(x)) {
out[i] <- ifelse (x[i] >= y[1] & x[i] <= y[2],
y[3],
ifelse (x[i] < y[1],
y[1], pre_comp))
}
out
}
fnct(c(1:150),c(20,80,50))
#> [1] 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 50 50 50 50 50 50
#> [26] 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50
#> [51] 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50
#> [76] 50 50 50 50 50 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80
#> [101] 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80
#> [126] 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80
Created on 2024-04-12 with reprex v2.1.0
*apply
loopThe loop but with a *apply
function becomes simpler, there is no need to create the results vector beforehand.
fnct <- function(x, y) {
pre_comp <- ifelse(max(x) - y[2] > y[1], y[2], NA)
sapply(x, \(xx) {
ifelse (xx >= y[1] & xx <= y[2],
y[3],
ifelse (xx < y[1],
y[1], pre_comp))
})
}
fnct(c(1:150),c(20,80,50))
#> [1] 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 50 50 50 50 50 50
#> [26] 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50
#> [51] 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50
#> [76] 50 50 50 50 50 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80
#> [101] 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80
#> [126] 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80
Created on 2024-04-12 with reprex v2.1.0
Following user @lotus's comment I realized that the loop is not needed at all.
fnct <- function(x, y) {
ifelse (x >= y[1] & x <= y[2],
y[3],
ifelse (x < y[1],
y[1],
ifelse(max(x) - y[2] > y[1],
y[2], NA)))
}
fnct(c(1:150),c(20,80,50))
#> [1] 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 50 50 50 50 50 50
#> [26] 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50
#> [51] 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50
#> [76] 50 50 50 50 50 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80
#> [101] 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80
#> [126] 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80
Created on 2024-04-12 with reprex v2.1.0