2014-10-27 52 views
4

我有兩個不同長度的數據幀。有一個將兩個數據幀鏈接在一起的獨特因素。我想將較大數據幀中的值乘以較小數據幀中的匹配因子。下面是代碼來演示:如何將兩個不等長度的向量乘以一個因子?

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]都乘以​​因爲因子「A」的匹配因素,其餘的比賽等等。

回答

3

對於這個問題,你也可以使用match,這應該是一定程度上比merge/transform approach更有效率(特別是如果你不需要data.frame後者創建):

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

# [1] 1 2 6 8 15 18 28 32 45 50 
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 
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最終結果