将数据框的列乘以矩阵中各自的单元格值

Multiplication of columns of a data frame to their respective cell value in a matrix

我必须将数据框的列与另一个矩阵中指定的单元格值相乘。根据定义,这意味着数据框的列数等于矩阵中的元素数。

例如,

我有一个这样的矩阵

         [,1]       [,2]   
[1,] 0.9470883 0.90148918
[2,] 0.6953117 0.69216633

和一个看起来像这样的数据框

  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

矩阵的每个单元格都必须乘以数据框的相应列。可以按行 wise/column 明智的方式读取矩阵。这样做(按行),字段将乘以

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

所以输出是

  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

我想用比 for 循环更快的方法对更大维度的矩阵和数据框执行此操作。

执行此操作的方法(不包含 id 列)是:

mapply('*', df, c(mat))

最终转换为数据帧:

as.data.frame(mapply('*', df, c(mat)))

示例:

as.data.frame(mapply('*', cars, c(100, 1000)))

关于 id 列,您需要稍微更改一下:

my.cars <- cbind(id=1:nrow(cars), cars)
cbind(my.cars[1], as.data.frame(mapply('*', my.cars[-1], c(100, 1000))))

所以在你的情况下:

cbind(df[1], as.data.frame(mapply('*', df[-1], c(mat))))
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
> 

我们也可以使用 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