Search code examples
rfor-loopdynamiccase

How can I make a Case_when with dynamic conditions to modify a continuous vector into ordinal vector of numbers in R?


I am building a dataset where I have a continuous variable from 0 to 1 that I would like to convert into an ordinal variable with N "levels". For example, I have many continuous numbers between 0 and 0.2 which need to all be to be converted to 0.1, then continuous numbers 0.2 to 0.4 to be converted to 0.2 etc.

Part of the importance of this is the dynamic ability to change the number of levels as my demonstration aims to show the effects of having more or less levels which can be modified dynamically.

To accomplish this, I've written out the below dynamic code within a for loop based upon my plan. I'm getting an error where my second condition fails to evaluate and the remainder return to default values.

Below is the dynamic code:

binN3 <- pretty (x$x, n = 40)
x$y <- seq(0,1, length.out = 100)
x <- as.data.frame(x)

for(i in 1:length(binN3)) {
  print(paste(i))
  print(paste(binN3[i]))
  
  x <- x %>%
  mutate(ordinal = case_when(
    y <= binN3[1] ~ 0,
    y <= binN3[i+1] ~ print(binN3[i]),
    .default = 999
  ))
}

Below is the Hard Code:

x <- x %>%
  mutate(linresp = case_when(
    x <= 0.02 ~ 0,
    x <= 0.04 ~ 0.02,
    x <= 0.06 ~ 0.04,
    .default ~ 999
  ))

The results of the dynamic code look like the following:

0, 999, 999, 999....

I'm quite confident that my error is within this line of code although I'm not sure how to change the syntax.

y <= binN3[i+1] ~ print(binN3[i])

The results of the hard code that I would like to replicate: 0, 0, 0, 0, 0.02, 0.02, 0.04, 0.04. etc...


Solution

  • The problem with your code is that mutate is going to evaluate every row of the dataframe on each iteration of the loop, so every row ends up getting compared to the last value of binN3.

    There isn't a declaration of the dataframe in your code so please let me know if this doesn't work for you, but I found a function that does what you're looking for:

    x$ordinal <- cut(x$y, breaks = length(binN3), labels = binN3)