我有两个不同长度的数据帧。有一个独特的因素将两个数据帧链接在一起。我想将较大数据帧中的值乘以较小数据帧中的匹配因子。以下是演示代码:
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”与其他匹配因子相匹配,等等。
答案 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