let's imagine you are doing something like this:
mutate(mtcars,
ff1 = hp wt*1,
ff2 = hp wt*2,
ff3 = hp wt*3,
ff4 = hp wt*4)
In this case we have just four new columns to create and it is quite easy to do it manually. However, imagine that you want to create 150 new columns in this way. It would be very tedious and time-consuming to write out all the individual ff =
stuff. It would be the easiest if we could do something like this:
mutate(mtcars,
ff = hp wt*seq(1:150))
However, this doesn't work because of this thing:
Error in `mutate()`:
! Problem while computing `ff = hp wt * seq(1:150)`.
✖ `ff` must be size 32 or 1, not 150.
So what is the proper syntax to achieve the desired output? Thanks.
CodePudding user response:
We could loop over the sequence with map
, then create the column with transmute
(so that it returns only a single column) by taking the sum of 'hp' and the 'wt' multiplied by the looped value. The =
doesn't evaluate an expression on the lhs, so we use :=
to evaluate (!!
) an expression created with paste/str_c
as new column name
library(purrr)
library(dplyr)
library(stringr)
map_dfc(1:150, ~ mtcars %>%
transmute(!! str_c('ff', .x) := hp wt * .x)) %>%
bind_cols(mtcars, .)
Or using base R
, use outer
to return the product of 'wt' and the sequence as a matrix
and add the hp column, create the new columns by assignment (<-
)
mtcars[paste0("ff", 1:150)] <- outer(mtcars$wt, 1:150) mtcars$hp