如何将两个不等长度向量乘以一个因子?

时间:2014-10-27 08:02:02

标签: r

我有两个不同长度的数据帧。有一个独特的因素将两个数据帧链接在一起。我想将较大数据帧中的值乘以较小数据帧中的匹配因子。以下是演示代码:

d1 <- data.frame(u = factor(x = LETTERS[1:5]), n1 = 1:5)
d2 <- data.frame(u = factor(x = rep(x = LETTERS[1:5], each = 2)), n2 = 1:10)

我希望d2[1:2, 2]两者都乘以d1[1, 2],因为因子“A”与其他匹配因子相匹配,等等。

3 个答案:

答案 0 :(得分:3)

使用merge加入两个数据框,然后transform为其添加一列。

> transform(merge(d1, d2), n.total = n1*n2)

   u n1 n2 n.total
1  A  1  1       1
2  A  1  2       2
3  B  2  3       6
4  B  2  4       8
5  C  3  5      15
6  C  3  6      18
7  D  4  7      28
8  D  4  8      32
9  E  5  9      45
10 E  5 10      50

如果您不需要transform创建的数据框,则可以改为使用with

> with(merge(d1, d2), n1*n2)

 [1]  1  2  6  8 15 18 28 32 45 50

如果您有大量数据并且上述解决方案太慢或效率低,我建议您选择@jbaums解决方案,但我发现merge的可读性提高更为可取。

> require(microbenchmark)
> microbenchmark(transform(merge(d1, d2), n.total = n1*n2),
+                with(merge(d1, d2), n1*n2),
+                d2$n2 * d1[match(d2$u, d1$u), 'n1'])

Unit: microseconds
                                        expr     min       lq       mean
 transform(merge(d1, d2), n.total = n1 * n2) 826.897 904.2275 1126.41204
                with(merge(d1, d2), n1 * n2) 658.295 722.6715  907.34581
         d2$n2 * d1[match(d2$u, d1$u), "n1"]  49.372  59.5830   78.42575
   median        uq      max neval cld
 940.3890 1087.0350 2695.521   100   c
 764.2965  934.5555 2463.300   100  b 
  66.2475   86.1505  260.820   100 a  

答案 1 :(得分:3)

对于这个问题,你也可以使用match,它应该比merge/transform approach更有效率(特别是如果你不需要后者创建的data.frame): / p>

d2$n2 * d1[match(d2$u, d1$u), 'n1']

# [1]  1  2  6  8 15 18 28 32 45 50

答案 2 :(得分:2)

如果我们进行速度比较,您也可以尝试data.table包(尽管对于这么小的数据集,jbaums方法可能更有效)

library(data.table)
setkey(setDT(d1), u); setDT(d2)
d1[d2][, n.total := n1*n2][]
#     u n1 n2 n.total
#  1: A  1  1       1
#  2: A  1  2       2
#  3: B  2  3       6
#  4: B  2  4       8
#  5: C  3  5      15
#  6: C  3  6      18
#  7: D  4  7      28
#  8: D  4  8      32
#  9: E  5  9      45
# 10: E  5 10      50

或(由@Arun建议)

d2[d1, n2 := n2*n1] # Update (by reference) `n2`

OR

d2[d1, new := n2*n1] # Add new column

注意:虽然这些会更快,但您不会在最终结果中看到列n1