将数据帧的列乘以矩阵中的相应单元值

时间:2015-12-19 10:13:29

标签: r dataframe matrix-multiplication

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

例如,

我有一个像这样的矩阵

         [,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

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

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循环更快。

3 个答案:

答案 0 :(得分:2)

执行此操作的方法(没有列id)是:

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

最终转换为dataframe:

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))))

答案 1 :(得分:2)

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
> 

答案 2 :(得分:1)

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