【发布时间】:2019-12-02 15:57:27
【问题描述】:
假设我有以下data.table:
library(data.table)
dt <- data.table(
a = c(1L, 1L, 2L, 2L),
b = c('A', 'A', NA_character_, NA_character_),
Amount = 1:4
)
我想执行笛卡尔连接以将权重应用于金额列,假设我有下表的权重:
set.seed(42L)
weights <- data.table(
a = c(rep(1L, 5L), rep(2L, 5L)),
b = LETTERS[1:10],
Weight = runif(10L)
)
获得我想要的东西的一种方法是:
rbind(
dt[a == 1L],
dt[a != 1L][
weights,
.(a, b = i.b, Amount = Amount * Weight),
on = c('a'),
nomatch = 0L,
allow.cartesian = TRUE
]
)
编辑:我同事的一项改进是对第一项的改进,但对性能没有太大帮助:
rbind(
dt[a == 1L],
dt[a != 1L][
weights,
modifyList(.SD, .(b = i.b, Amount = Amount * Weight)),
on = c('a'),
nomatch = 0L,
allow.cartesian = TRUE
]
)
导致:
a b Amount
1: 1 A 1.0000000
2: 1 A 2.0000000
3: 2 F 1.5572878
4: 2 F 2.0763838
5: 2 G 2.2097649
6: 2 G 2.9463533
7: 2 H 0.4039998
8: 2 H 0.5386664
9: 2 I 1.9709769
10: 2 I 2.6279692
11: 2 J 2.1151944
12: 2 J 2.8202591
我想知道/改进两件事:
- 如果列数增加,则需要在最后的代码块中指定所有列
.(a, b = i.b, Amount = Amount * Weight)继续增加。 - 如果行数增加到数百万,是否有更有效的方法?
【问题讨论】:
-
我很困惑。这是否会产生预期的结果:
dt[, Amount := Amount + 0]; dt[weights, Amount := Amount * i.Weight, on = .(a, b)]? -
@mt1022 我不这么认为,请参阅我的编辑。
标签: r join data.table