1

I'm inexperienced with for loops and try to write for loop in R for several columns from a df dataset. Each column I'm interested in has values from 1 to 15 or NA. "names" is a list of names of those columns:

>names

[1] "score"  "rate"   "asset"     "capital"  "earning"  "ast" "liquid"  "profit"  "assesment" "factor" 

I want to replace their values with groups such as "1-5", "6-10", "11-15". I tried following code:

for (i in names){

    df <- mutate(df, i = 
                       ifelse(df$i >= 1 & df$i <= 5 , "1-5", 
                           ifelse(df$i >= 6 & df$i <= 10, "6-10",
                                ifelse(df$i >= 11 & df$i <= 15, "11-15",NA)))))
    }

But got an error:

Error: Column i must be length 2511 (the number of rows) or one, not 0

Could you please help/advice how to write such for loop and to solve this task.

Bambeil
  • 309
  • 1
  • 8

1 Answers1

1

If we want to do this in tidyverse, use across to loop over the columns and use case_when instead of nested ifelse.

library(dplyr)
df <- df %>%
   mutate(across(all_of(names), ~ case_when(.x >=1 & .x <=5 ~ "1-5",
              .x >= 6 & .x <= 10 ~  "6-10",
               .x >= 11 & .x <= 15 ~  "11-15")))

These can be done in a more easier way with cut or findInterval

df <- df %>%
      mutate(across(all_of(names), cut, breaks = c(-Inf, 1, 6, 11, 15, Inf)))

In the for loop there are multiple issues i.e. i= create a column named i and not the values in i. In addition, $i will extract the i column if present and not the value of the column, use [[ (here, both are not needed as we could convert to symbol and evaluate (!!) or extract the column with [[ from .data

for (i in names){

    df <- mutate(df, !!i := 
                       ifelse(.data[[i]] >= 1 & .data[[i]] <= 5 , "1-5", 
                           ifelse(.data[[i]] >= 6 & .data[[i]] <= 10, "6-10",
                             ifelse(.data[[i]] >= 11 & 
                .data[[i]] <= 15, "11-15",NA)))))
    }
akrun
  • 874,273
  • 37
  • 540
  • 662