Mutate all columns matching a pattern each time based on the previous columns
This is actually vectorised operation so you can do this without any loops.
Using vector recycling :
df[, c(FALSE, TRUE)] <- df[, c(FALSE, TRUE)]/100 * df[, c(TRUE, FALSE)]
df
# a fooa b foob c fooc
#1 0.5543269 0.003664775 48.26791 1.49628246 98.06053 5.918428
#2 -0.2802719 -0.002461827 51.15647 0.08114656 113.96432 2.620614
#3 1.7751634 0.015808878 52.34582 1.20765132 101.00663 9.765657
#4 0.1873201 0.001060757 50.58978 0.83478430 98.85561 5.976363
#5 1.1425261 0.006781434 50.35224 1.59495949 107.02225 6.845194
If you want to perform this based on names of the column.
cols <- grep('foo', names(df))
df[cols] <- df[cols]/100 * df[-cols]
One option could be:
df %>%
mutate(across(starts_with("foo"))/100 * across(!matches("foo")))
a fooa b foob c fooc
1 0.5543269 0.003664775 48.26791 1.49628246 98.06053 5.918428
2 -0.2802719 -0.002461827 51.15647 0.08114656 113.96432 2.620614
3 1.7751634 0.015808878 52.34582 1.20765132 101.00663 9.765657
4 0.1873201 0.001060757 50.58978 0.83478430 98.85561 5.976363
5 1.1425261 0.006781434 50.35224 1.59495949 107.02225 6.845194
Here is another approach using across()
and cur_column()
. I personally would not recommend to make calculations based on the position of columns, and would instead recommend to work with the columns names, since this seems safer.
In the example below we loop over the columns a
,b
and c
with across
and access the values of each corresponding foo
column by using get()
and cur_column
.
set.seed(13)
dfrows = 5
df = data.frame(a = rnorm(dfrows),
fooa = runif(dfrows),
b = rnorm(dfrows, mean=50, sd=5),
foob = runif(dfrows, min=0, max=5),
c = rnorm(dfrows, mean=100, sd=10),
fooc = runif(dfrows, min=0, max=10))
library(dplyr)
df %>%
mutate(across(matches("^[a-z]$"),
~ get(paste0("foo", cur_column())) / 100 * .x,
.names = "foo{col}"))
#> a fooa b foob c fooc
#> 1 0.5543269 0.003664775 48.26791 1.49628246 98.06053 5.918428
#> 2 -0.2802719 -0.002461827 51.15647 0.08114656 113.96432 2.620614
#> 3 1.7751634 0.015808878 52.34582 1.20765132 101.00663 9.765657
#> 4 0.1873201 0.001060757 50.58978 0.83478430 98.85561 5.976363
#> 5 1.1425261 0.006781434 50.35224 1.59495949 107.02225 6.845194
Created on 2021-01-27 by the reprex package (v0.3.0)