saladi saladi - 2 months ago 6
R Question

What is the right way to multiply a named vector by a dataframe?

Similar to this SO question, what is the right way to multiply a named vector by a dataframe, such that each row is multiplied by corresponding element of the vector?

df <- data.frame(A=1:5, B=2:6)
v <- c(2, 0)
names(v) <- c("B", "A")


I would like the following output:

A B
1 0 4
2 0 6
3 0 8
4 0 10
5 0 12


None of the suggested solutions from the other question match column names with the names of the vector. For example,

dt <- data.table(df)
for (i in seq_along(dt))
dt[, i := dt[[i]] * v[i], with = F]

dt
A B
1: 2 0
2: 4 0
3: 6 0
4: 8 0
5: 10 0


I can do it by reordering v, but I wonder whether there's a better way to do this:

v <- v[colnames(df)]

Answer

How about this:

r <- mapply('*', df, v[names(df)])
# or equivalently: mapply(function(x,y) x*y, df, v[names(df)])

#     A  B
#[1,] 0  4
#[2,] 0  6
#[3,] 0  8
#[4,] 0 10
#[5,] 0 12

v[names(df)] will give the vector elements in the same order as they are in df, so column-name-respective, so to say.

If you want to have r as data frame, just do as.data.frame(r).

This is from ?mapply

mapply is a multivariate version of sapply. mapply applies FUN to the first elements of each ... argument, the second elements, the third elements, and so on. Arguments are recycled if necessary.

FUN is * in our setting.