Reputation: 67
Suppose I am working with the mtcars dataset, and I would like to add:
1 to all values in the column: mpg
2 to all values in the column: cyl
3 to all values in the column: disp
I would like to keep all columns in mtcars, and refer to the columns by their names rather than their index.
Here's my current attempt:
library("tidyverse")
library("rlang")
data(mtcars)
mtcars_colnames <- quo(c("mpg", "cyl", "disp"))
num <- c(1, 2, 3)
mtcars %>% mutate(across(!!! mtcars_colnames, function(x) {x + num[col(.)]}))
I'm stuck on how to dynamically add (1,2,3) to columns (mpg, cyl, disp). Thanks in advance.
Upvotes: 0
Views: 158
Reputation: 388982
Here are 3 base R approaches :
mtcars_colnames <- c("mpg", "cyl", "disp")
num <- c(1, 2, 3)
df <- mtcars
#option 1
df[mtcars_colnames] <- sweep(df[mtcars_colnames], 2, num, `+`)
#option 2
df[mtcars_colnames] <- Map(`+`, df[mtcars_colnames], num)
#option 3
df[mtcars_colnames] <- t(t(df[mtcars_colnames]) + num)
Upvotes: 1
Reputation: 887118
We could change the input by passing just a vector of strings instead of quo
sures and a named vector for 'num', then use the cur_column
inside the across
to match with the named vector of 'num', get the corresponding value and do the addition
library(dplyr)
mtcars_colnames <- c("mpg", "cyl", "disp")
num <- setNames(c(1, 2, 3), mtcars_colnames)
mtcars1 <- mtcars %>%
mutate(across(all_of(mtcars_colnames), ~ num[cur_column()] + .))
-check the output
# // old data
mtcars %>%
select(all_of(mtcars_colnames)) %>%
slice_head(n = 5)
# mpg cyl disp
#Mazda RX4 21.0 6 160
#Mazda RX4 Wag 21.0 6 160
#Datsun 710 22.8 4 108
#Hornet 4 Drive 21.4 6 258
#Hornet Sportabout 18.7 8 360
# // new data
mtcars1 %>%
select(all_of(mtcars_colnames)) %>%
slice_head(n = 5)
# mpg cyl disp
#Mazda RX4 22.0 8 163
#Mazda RX4 Wag 22.0 8 163
#Datsun 710 23.8 6 111
#Hornet 4 Drive 22.4 8 261
#Hornet Sportabout 19.7 10 363
Or if we prefer to pass a unnamed 'num' vector, then match
the cur_column
with the 'mtcars_colnamesinside the
across` to return the index and then use that to subset the 'num'
mtcars1 <- mtcars %>%
mutate(across(all_of(mtcars_colnames),
~ num[match(cur_column(), mtcars_colnames)] + .))
Upvotes: 1