 # Multiple if/else if statements using a previously created vector.

I'm trying to create a function that assigns a new value to previously created values for a formula I am trying to create. The vector I am using is a z-score and then I am trying to assign "points" to each z-score to add to the rest of my formula.

I have struggled first with pulling in a previous vector to use in the function as the only argument, and am now continuously getting errors due to the list of if & else if statements I have created. Any help on how to perfect this, not get errors, and have the correct script would be appreciated!!

** note: I have tried else if, else, and ifelse statements all for the list and I still get errors.**

#this is the z-score calculation for wellness#
wellness_z <- ((wellness_sum- alltime_wellness_sum)/ sd_wellness)

wellness_score <- function(wellness_z)
if (wellness_z==0 )
return(1)
if (wellness_z>=0.01 && wellness_z<=0.49)
return(2)
if (wellness_z>=0.50 && wellness_z<=0.99)
return(3)
if (wellness_z>=1.00 && wellness_z<=1.49)
return(4)
if (wellness_z>=1.50 && wellness_z<=1.99)
return(5)
if (wellness_z>=2.00 && wellness_z<=2.49)
return(6)
if (wellness_z>=2.50 && wellness_z<=2.99)
return(7)
if (wellness_z<=-0.01 && wellness_z>=-0.49)
return(-2)
if (wellness_z<=-0.50 && wellness_z>=-0.99)
return(-3)
if (wellness_z<=-1.00 && wellness_z>=-1.49)
return(-4)
if (wellness_z<=-1.50 && wellness_z>=-1.99)
return(-5)
if (wellness_z<=-2.00 && wellness_z>=-2.49)
return(-6)
if (wellness_z<=-2.50 && wellness_z>=-2.99)
return(-7)

One option to make this less painful is to use the `cut` function. For example:

``````# Fake data
set.seed(2)
y = c(0, runif(50, 0, 3))

breaks = c(-Inf, 0, 0.05, 0.25, 0.5, 1, 1.5, 2.5, Inf)
labels = c(1:4,-3:(-6))

# Returns default category labels as factors
cut(y, breaks=breaks, include.lowest=TRUE)

# Returns desired labels, but as factors
cut(y, breaks=breaks, labels=labels, include.lowest=TRUE)

# Convert factor labels to numeric
y_score = as.numeric(as.character(cut(y, breaks=breaks, labels=labels, include.lowest=TRUE)))
``````
``````y_score
  1 -3 -5 -5 -3 -6 -6  4 -6 -4 -5 -5 -3 -5 -3 -4 -6 -6 -3
 -4  3 -5 -4 -6  4 -4 -4  4 -4 -6  4  2  4 -5 -6 -5 -5 -6
 -3 -5  4 -6 -3  4  4 -6 -5 -6 -4 -5 -5
``````

For your actual use case, you'll need to create the vectors of `breaks` and `labels` based on how you actually want to recode the values. Also, the `cut` function allows you to decide whether you want each interval closed on the left or the right. See the help (`?cut`) for details. The `cut` function returns a vector of factor class. `as.numeric(as.character(...` converts the labels back to numeric so that you can use them in further calculations.

To turn this into a function:

``````wellness_z = function(x) {

breaks = c(0, 0.01, 0.05, 0.1, 0.5, 1, 1.5, 2.5, Inf)
labels = c(1:4,-3:(-6))

as.numeric(as.character(cut(x, breaks=breaks, labels=labels, include.lowest=TRUE)))

}

wellness_z(y)
``````

I think `cut` is a better approach for your use case, but here are a few examples with `ifelse` and `if`.

The if/else approach would be something like the following, but with additional nested `ifelse` statements for each range you want to assign to a value. `ifelse` is "vectorized" meaning that it operates separately on every element of the input vector:

``````wellness_z = function(x) {
ifelse(x==0, 1,
ifelse(x > 0 & x < 0.5, 2,
ifelse(x >= 0.5 & x < 1, 3, 4)))
}

wellness_z(y)
``````

The `if` statement approach doesn't work, because `if` is not vectorized; it looks only at the first value of the input vector:

``````wellness_z = function(x) {
if(x==0) {
1
} else if(x > 0 & x < 0.5) {
2
} else if(x >= 0.5 & x < 1) {
3
} else {
4
}
}
``````
``````wellness_z(y)
``````
`````` 1
Warning message:
In if (x == 0) { :
the condition has length > 1 and only the first element will be used
``````

However, you can use the base R `sapply` function or the `purrr` `map` function to operate on each element individually:

``````sapply(y, wellness_z)

purrr::map_dbl(y, wellness_z)
``````

This topic was automatically closed 21 days after the last reply. New replies are no longer allowed.