Home > OS >  How to create incremental column name with conditions? (R)
How to create incremental column name with conditions? (R)

Time:03-20

I would like to create new columns with incremental numbers in its name (dist100, dist200, dist300) in df with a if/else condition that evaluates the value from dist (1 = true; 0 = false).

df_desire is the desired output.

df <- tibble(ID=c(1001, 1002, 1003, 1004), dist=c(200, 400, 100, 300))
df_desire <- tibble(ID=c(1001, 1002, 1003, 1004), dist=c(200, 400, 100, 300), dist100=c(0, 0, 1, 0), dist200=c(1, 0, 1, 0), dist300=c(1, 0, 1, 1))

I tried using the following code, but I get an error message:

df_output <- df %>% 
  mutate(
    paste0("dist", seq(100, 300, by = 100)) = ifelse(dist <= paste0("dist", seq(100, 300, by = 100)), 1, 0))

Error: unexpected '=' in:
"  mutate(
    paste0("dist", seq(100, 300, by = 100)) ="

CodePudding user response:

You can do something like this:

new_cols = lapply(seq(100,300,100), \(x) as.numeric(df$dist<=x))
names(new_cols) <- paste0("dist",seq(100,300,100))
bind_cols(df,as.data.frame(new_cols))

     ID  dist dist100 dist200 dist300
  <dbl> <dbl>   <dbl>   <dbl>   <dbl>
1  1001   200       0       1       1
2  1002   400       0       0       0
3  1003   100       1       1       1
4  1004   300       0       0       1

Or, similarly within one pipeline you can do this:

vals = seq(100,300,100)
bind_cols(
  df,
  map(vals, \(x) 1*(df$dist<=x)) %>% setNames(paste0("dist",vals)))
)

CodePudding user response:

data.table option

library(data.table)

vals <- seq(100, 300, by = 100)
cols <- paste0("dist", vals)
setDT(df)
df[, (cols) := lapply(vals, function(x)  (dist <= x))]
df

#     ID dist dist100 dist200 dist300
#1: 1001  200       0       1       1
#2: 1002  400       0       0       0
#3: 1003  100       1       1       1
#4: 1004  300       0       0       1

CodePudding user response:

a few ways to do this but rename_with is really handy depending on the context

  1. create the columns
  2. use rename_with to select the columns you want to rename
  3. use formula to apply renaming logic
df %>% 
mutate(a=ifelse(dist==100,1,0),
         b=ifelse(dist<=200,1,0),
         c=ifelse(dist<=300,1,0)) %>% 
  rename_with(.cols = -c(1:2), #use tidyselect verbs to select the cols you wan to rename
              .fn = ~glue::glue("dist{seq(100,300,by=100)}")) 

Inspired by the above answer (as it taught me something), I show an alternative approach with tidy packages. Not as readable but effective.

df[,c(glue::glue("dist{seq(100,300,by=100)}"))] <- map(seq(100,300,by=100),~as.numeric(df$dist<=.x))
  •  Tags:  
  • r
  • Related