我应该如何开始考虑我更喜欢哪种语法?
我的标准是效率(这是第一位)以及可读性/可维护性。
此
A <- B[A, on = .(id)] # wow such. concision
或者那个
A[B, on = .(id), comment := i.comment]
甚至(如PoGibas建议的那样):
A <- merge(A, B, all.x = TRUE)
为了完整起见,一种更基本的方法是使用match()
:
A[, comment := B[chmatch(A[["id"]], id), comment]]
示例数据:
library(data.table)
A <- data.table(id = letters[1:10], amount = rnorm(10)^2)
B <- data.table(id = c("c", "d", "e"), comment = c("big", "slow", "nice"))
答案 0 :(得分:14)
为了效率和可维护性,我更喜欢“更新联接”的习惯用法:**
DT[WHERE, v := FROM[.SD, on=, x.v]]
它是vignette("datatable-reference-semantics")
中“通过引用更新某些列的行-通过引用 sub-assign ”显示的内容的扩展。一旦在连接上有一个小插图可用,那也应该是一个很好的参考。
这是有效的,因为它仅使用WHERE
选择的行并就地修改或添加该列,而不是像更简洁的左联接FROM[DT, on=]
那样创建新表。
这使我的代码更具可读性,因为我可以很容易地看到联接的重点是添加列v
;而且我不必考虑SQL中的“左” /“右”行话,也不必考虑联接后是否保留行数。
这对代码维护很有用,因为如果以后我想找出DT
如何获得名为v
的列,则可以在我的代码中搜索v :=
,而{{1} }掩盖了要添加的新列。另外,它允许使用FROM[DT, on=]
条件,而左联接则不允许。例如,如果using FROM
to "fill" NAs in an existing column v
,这可能很有用。
与其他更新联接方法WHERE
相比,我可以想到两个优点。第一种是使用DT[FROM, on=, v := i.v]
子句的选项,第二种是在连接出现问题时通过警告(例如,以WHERE
为条件的FROM
中的重复匹配)来通过警告透明。这是扩展OP示例的图示:
on=
在左联接风格的更新中,即使library(data.table)
A <- data.table(id = letters[1:10], amount = rnorm(10)^2)
B2 <- data.table(
id = c("c", "d", "e", "e"),
ord = 1:4,
comment = c("big", "slow", "nice", "nooice")
)
# left-joiny update
A[B2, on=.(id), comment := i.comment, verbose=TRUE]
# Calculated ad hoc index in 0.000s elapsed (0.000s cpu)
# Starting bmerge ...done in 0.000s elapsed (0.000s cpu)
# Detected that j uses these columns: comment,i.comment
# Assigning to 4 row subset of 10 rows
# my preferred update
A[, comment2 := B2[A, on=.(id), x.comment]]
# Warning message:
# In `[.data.table`(A, , `:=`(comment2, B2[A, on = .(id), x.comment])) :
# Supplied 11 items to be assigned to 10 items of column 'comment2' (1 unused)
id amount comment comment2
1: a 0.20000990 <NA> <NA>
2: b 1.42146573 <NA> <NA>
3: c 0.73047544 big big
4: d 0.04128676 slow slow
5: e 0.82195377 nooice nice
6: f 0.39013550 <NA> nooice
7: g 0.27019768 <NA> <NA>
8: h 0.36017876 <NA> <NA>
9: i 1.81865721 <NA> <NA>
10: j 4.86711754 <NA> <NA>
有两个匹配项,您也默默地获得了comment
的最终值;而在其他更新中,您会收到一条有用的警告消息(已升级为an error in a future release)。甚至使用左联接方法打开id == "e"
也不提供信息-它说有四行被更新,但没有说一行被更新了两次。
我发现,当我的数据排列在一组整洁/关系表中时,这种方法最有效。 Hadley Wickham's paper是一个很好的参考。
**在此惯用语中,verbose=TRUE
部分应使用连接列名称和规则(例如on=
或on=.(id)
)填充。可以使用on=.(from_date >= dt_date)
,roll=
和mult=
传递更多的加入规则。有关详细信息,请参见nomatch=
。感谢@RYoda在评论中指出这一点。
这里是Matt Dowle解释?data.table
:Find time to nearest occurrence of particular value for each row