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
- create the columns
- use
rename_with
to select the columns you want to rename - 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))