What is the tidy equivalent of using `sweep` across rows?

Say I have a set of columns, named Intercept, 1, 2, 3 in my example, and a set of coefficients, named c0 through c3.

xs<-seq(.1,1,.1)
X <- cbind(Intercept=1, "1"=xs, "2"=xs^2, "3"=xs^3)
coefs <- c(c0=10, c1=2, c2=.5, c3=-1)

I want to multiply each column of X by the the corresponding coefficient.

sweep(
  X,     # x: the data array
  2,     # MARGIN: 2, to sweep across rows
  coefs, # STATS: just the array of coefficients
  `*`)   # FUN: the function to use is multiplication

This gives what I want.

But if I had my data as a tibble (tidyX <- as_tibble(X)), what is the tidy way of doing this?

tidyX %>% ... ?

It seems simple, and I imagine it involves dplyr::rowwise(), perhaps, but I don't see the idiomatic way of doing this.


Solution 1:

Ah, just as soon as I finally post, I found an answer.

tidyX %>% 
  rowwise() %>% 
  mutate(across() * coefs)

I still find this syntax nonintuitive, but that does just what I'm looking for.

Solution 2:

If the column names are the same, we may loop across the columns of 'tidyX' and use the column name (cur_column()) to extract the corresponding column of 'coefs'. But, here the column name is different, so use match to get the column index, extract ([[) the column/element (if it is a named vector) from 'coefs' and multiply

library(dplyr)
tidyX %>% 
   mutate(across(everything(), 
         ~ .x * coefs[[match(cur_column(), names(tidyX))]]))

Or an easier option is map2 (from purrr) to loop over the corresponding columns of both datasets and multiply. If we want the output as a tibble/data.frame, use _dfc

library(purrr)
map2_df(tidyX, coefs, `*`)
# A tibble: 10 × 4
   Intercept   `1`   `2`    `3`
       <dbl> <dbl> <dbl>  <dbl>
 1        10   0.2 0.005 -0.001
 2        10   0.4 0.02  -0.008
 3        10   0.6 0.045 -0.027
 4        10   0.8 0.08  -0.064
 5        10   1   0.125 -0.125
 6        10   1.2 0.18  -0.216
 7        10   1.4 0.245 -0.343
 8        10   1.6 0.32  -0.512
 9        10   1.8 0.405 -0.729
10        10   2   0.5   -1