将数据框的列乘以矩阵中各自的单元格值
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
我必须将数据框的列与另一个矩阵中指定的单元格值相乘。根据定义,这意味着数据框的列数等于矩阵中的元素数。
例如,
我有一个这样的矩阵
[,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