Reputation: 108
I have to multiply columns of a data frame with an assigned cell value from another matrix. This would, by definition, mean that the number of columns of data frame are equal to number of elements in the matrix.
For eg,
I have a matrix like this
[,1] [,2]
[1,] 0.9470883 0.90148918
[2,] 0.6953117 0.69216633
and a data frame which looks like this
id val1 val2 val3 val4
1 1 1 1 3 5
2 2 2 1 3 5
3 3 1 1 4 5
4 4 2 1 4 5
5 5 1 1 3 6
6 6 2 1 3 6
7 7 1 1 4 6
8 8 2 1 4 6
Each cell of matrix has to be multiplied by respective column of data frame. The matrix can be read in row wise/column wise fashion. Doing this (row wise) the fields would be multiplied as
df$val1 <- df$val1*mat[1,1] #mat[1,1] is 0.9470883
df$val2 <- df$val2*mat[1,2] #mat[1,2] is 0.90148918
df$val3 <- df$val3*mat[2,1] #mat[2,1] is 0.6953117
df$val4 <- df$val4*mat[2,2] #mat[2,2] is 0.69216633
So that the output is
id val1 val2 val3 val4
1 1 0.9470883 0.9014892 2.085935 3.460832
2 2 1.8941766 0.9014892 2.085935 3.460832
3 3 0.9470883 0.9014892 2.781247 3.460832
4 4 1.8941766 0.9014892 2.781247 3.460832
5 5 0.9470883 0.9014892 2.085935 4.152998
6 6 1.8941766 0.9014892 2.085935 4.152998
7 7 0.9470883 0.9014892 2.781247 4.152998
8 8 1.8941766 0.9014892 2.781247 4.152998
I want to do this over bigger dimensions of matrix and data frame with something faster than for-loops.
Upvotes: 0
Views: 241
Reputation: 887981
We could also use the sweep
df[-1] <- sweep(df[-1], MARGIN=2, c(t(mat)), '*')
df
# id val1 val2 val3 val4
#1 1 0.9470883 0.9014898 2.085935 3.460832
#2 2 1.8941766 0.9014898 2.085935 3.460832
#3 3 0.9470883 0.9014898 2.781247 3.460832
#4 4 1.8941766 0.9014898 2.781247 3.460832
#5 5 0.9470883 0.9014898 2.085935 4.152998
#6 6 1.8941766 0.9014898 2.085935 4.152998
#7 7 0.9470883 0.9014898 2.781247 4.152998
#8 8 1.8941766 0.9014898 2.781247 4.152998
Upvotes: 1
Reputation: 12569
The way to do this (without the column id
) is:
mapply('*', df, c(mat))
Eventually convert to dataframe:
as.data.frame(mapply('*', df, c(mat)))
Example:
as.data.frame(mapply('*', cars, c(100, 1000)))
With respect to the column id
you have a little bit to change:
my.cars <- cbind(id=1:nrow(cars), cars)
cbind(my.cars[1], as.data.frame(mapply('*', my.cars[-1], c(100, 1000))))
So in your case:
cbind(df[1], as.data.frame(mapply('*', df[-1], c(mat))))
Upvotes: 2
Reputation: 2960
df <- read.table( header=TRUE,
text = "id val1 val2 val3 val4
1 1 1 3 5
2 2 1 3 5
3 1 1 4 5
4 2 1 4 5
5 1 1 3 6
6 2 1 3 6
7 1 1 4 6
8 2 1 4 6")
M <- matrix( c(0.9470883,0.90148918,0.6953117,0.69216633), byrow=TRUE )
df[,-1] <- t( t(as.matrix(df[,-1])) * rep(t(M),nrow(df)) )
.
> df
id val1 val2 val3 val4
1 1 0.9470883 0.9014892 2.085935 3.460832
2 2 1.8941766 0.9014892 2.085935 3.460832
3 3 0.9470883 0.9014892 2.781247 3.460832
4 4 1.8941766 0.9014892 2.781247 3.460832
5 5 0.9470883 0.9014892 2.085935 4.152998
6 6 1.8941766 0.9014892 2.085935 4.152998
7 7 0.9470883 0.9014892 2.781247 4.152998
8 8 1.8941766 0.9014892 2.781247 4.152998
>
Upvotes: 2