虽然看起来很简单,但我无法完成这项工作。 我想将矩阵(或数据帧或数据表)b中的每一行乘以向量a。
a <- data.table(t(1:4))
b <- matrix(data=2, nrow=3, ncol=4)
所需的输出(矩阵,数据帧或数据表格式):
[,1] [,2] [,3] [,4]
[1,] 2 4 6 8
[2,] 2 4 6 8
[3,] 2 4 6 8
任何人都可以帮助我(有效地)如何做到这一点吗?
答案 0 :(得分:3)
b*rep(unlist(a),each=nrow(b))
# [,1] [,2] [,3] [,4]
# [1,] 2 4 6 8
# [2,] 2 4 6 8
# [3,] 2 4 6 8
如果您定义b*rep(a,each=nrow(b))
,请或仅a <- 1:4
它只是一个矢量化元素明智的乘法,没有来自rep
的变换appart。
编辑:
似乎代表正在减缓我的解决方案。这是一个基准测试,其中包含一个预先计算的rep选项,以及一些关于扫描选项的改进(仅从源代码中获取相关部分)。
a <- data.table(t(1:200))
b <- matrix(data=2, nrow=100000, ncol=200)
a_vec <- unlist(a)
rep_a <- rep(a_vec,each=nrow(b))
microbenchmark::microbenchmark(
mkr1 = a[,lapply(.SD,function(x)(x*b[,x]))],
mkr2 = t(t(b) * (as.matrix(a)[1,])),
mkr_update = a[,lapply(V1:V4,function(i)(a[[i]]*b[,i]))],
mm = b*rep(unlist(a),each=nrow(b)),
mm_cheat = b*rep_a,
regular_sweep = sweep(b,2,unlist(a),`*`),
regular_sweep2 = sweep(b,2,a_vec,`*`),
improved_sweepA1 = b*aperm(array(unlist(a),rev(dim(b)))),
improved_sweepA2 = b*aperm(array(a_vec,rev(dim(b)))),
improved_sweepB1 = b*a[rep_len(1,nrow(b)),],
improved_sweepB2 = b*t(a_vec)[rep_len(1,nrow(b)),],
unit = "relative",
times=50)
Unit: relative
expr min lq mean median uq max neval
mkr1 42.12228 44.15266 50.23959 46.35240 57.20280 65.07289 50
mkr2 114.58427 124.19653 125.25660 131.08677 124.17058 114.91137 50
mkr_update 1.00000 1.00000 1.00000 1.00000 1.00000 1.00000 50
mm 231.34331 223.74365 217.50145 225.91117 215.90765 165.64814 50
mm_cheat 13.38838 13.22556 14.94682 13.36649 12.95260 25.15564 50
regular_sweep 96.15758 124.26746 121.04428 128.67282 129.19407 119.20210 50
regular_sweep2 97.79001 124.69191 124.74650 134.64249 134.97407 107.47152 50
improved_sweepA1 96.57837 124.86189 116.93736 127.08909 124.92805 105.83318 50
improved_sweepA2 96.27737 122.49773 118.45262 128.13369 126.15029 106.58669 50
improved_sweepB1 214.95773 227.39523 226.04339 248.38553 232.50401 161.45341 50
improved_sweepB2 31.20967 32.61873 37.74552 33.70969 41.52149 55.93362 50
答案 1 :(得分:2)
选项#1:使用data.table
功能:
注意:它的工作原理是因为列号和值匹配a
a[,lapply(.SD,function(x)(x*b[,x]))]
# V1 V2 V3 V4
#1: 2 4 6 8
#2: 2 4 6 8
#3: 2 4 6 8
选项#2:可以是:
t(t(b) * (as.matrix(a)[1,]))
[,1] [,2] [,3] [,4]
[1,] 2 4 6 8
[2,] 2 4 6 8
[3,] 2 4 6 8
<强>更新强>
选项#3:处理a
#Cases when `a` contains decimal values can be handled as
a <- data.table(t(c(1, 0.24, 3, 4)))
b <- matrix(data=2, nrow=3, ncol=4)
a[,lapply(V1:V4,function(i)(a[[i]]*b[,i]))]
# V1 V2 V3 V4
#1: 2 0.48 6 8
#2: 2 0.48 6 8
#3: 2 0.48 6 8
答案 2 :(得分:2)
在我这边,我会使用R的内置方法进行矩阵乘法%*%
。
考虑向量:[NB:data.table
不 vector
]
a <- c(1:4)
并考虑矩阵:
b <- matrix(data=2, nrow=3, ncol=4)
您的输出由:
给出output <- b %*% diag(a)
[,1] [,2] [,3] [,4]
[1,] 2 4 6 8
[2,] 2 4 6 8
[3,] 2 4 6 8
sweep
:sweep(b, 2, a, FUN = "*")
[,1] [,2] [,3] [,4]
[1,] 2 4 6 8
[2,] 2 4 6 8
[3,] 2 4 6 8
答案 3 :(得分:2)
感谢您的回复。我已经测试了上面建议的解决方案的速度(我的矢量和矩阵的实际大小),以使用最有效的解决方案:
a <- data.table(t(1:200))
b <- matrix(data=2, nrow=100000, ncol=200)
system.time(sweep(b, MARGIN=2, t(a), "*"))
# user system elapsed
# 0.31 0.06 0.39
system.time(a[,lapply(.SD,function(x)(x*b[,x]))])
# user system elapsed
# 0.2 0.0 0.2
#system.time(bind_rows(apply(b,1,`*`,a)))
#took 100+ so stopped it manually
system.time(t(t(b)*(as.matrix(a)[1,])))
# user system elapsed
# 0.31 0.05 0.36
system.time(apply(b, 1, `*`, 1:200))
# user system elapsed
# 1.20 0.11 1.31
system.time(b*rep(unlist(a),each=nrow(b)))
# user system elapsed
# 0.83 0.05 0.89
system.time(b*rep((1:200),each=nrow(b)))
# user system elapsed
# 0.36 0.06 0.42
答案 4 :(得分:1)
dplyr::bind_rows(apply(b, 1, `*`, a))
V1 V2 V3 V4
1: 2 4 6 8
2: 2 4 6 8
3: 2 4 6 8
棘手的部分是你的a
是一个data.table。如果它实际上是一个向量,那么它就更简单了:
apply(b, 1, `*`, 1:4)
[,1] [,2] [,3]
[1,] 2 2 2
[2,] 4 4 4
[3,] 6 6 6
[4,] 8 8 8