当前位置: 首页 > 知识库问答 >
问题:

左连接(一列)首选哪个data.table语法

萧远
2023-03-14

我应该如何开始考虑我更喜欢哪种语法?

我的标准是效率(这是第一)和易读性/可运维性。

A <- B[A, on = .(id)] # very concise!

或者说

A[B, on = .(id), comment := i.comment]

或者甚至(正如PoGibas所建议的):

A <- merge(A, B, all.x = TRUE)

为了完整起见,更基本的方法是使用< code>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"))

共有1个答案

左恺
2023-03-14

为了效率和可运维性,我更喜欢“更新连接”习语:**

DT[WHERE, v := FROM[.SD, on=, x.v]]

它是“通过引用更新某些列行 - 通过引用进行子分配”下的小插(“数据表引用语义”)中所示内容的扩展。一旦在连接上有可用的小插图,那也应该是一个很好的参考。

这是有效的,因为它只使用 WHERE 选择的行,并修改或添加列就地,而不是像更简洁的左联接 FROM[DT, on=] 那样创建一个新表。

这使得我的代码可读性更好,因为我可以很容易地看出连接的要点是添加列< code > v ;而且我不必考虑SQL中的“左”/“右”术语,也不必考虑连接后行数是否保持不变。

它对代码维护很有用,因为如果我以后想了解DT如何获得一个名为v的列,我可以在代码中搜索v :=,而FORROM[DT,on=]会掩盖正在添加哪些新列。此外,它允许 WHERE 条件,而左连接则不允许。例如,如果使用 FROM 来“填充”现有列 v 中的 NA,这可能很有用。

与其他更新连接方法DT[from, on=, v:=i. v]相比,我可以想到两个优点。首先是使用WHERE子句的选项,其次是在连接出现问题时通过警告实现透明度,例如From中的重复匹配以on=规则为条件。这是扩展OP示例的示例:

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>

在左联接风格的更新中,即使 id == “e” 有两个匹配项,您也会静默地获得注释的最终值;而在另一个更新中,您会收到一条有用的警告消息(在将来的版本中已升级为错误)。即使使用左连接方法打开 verbose=TRUE 也没有提供信息 - 它说有四行正在更新,但没有说一行正在更新两次。

我发现,当我的数据被安排到一组整洁/关系表中时,这种方法效果最好。哈德利·威克姆的论文就是一个很好的参考。

** 在此成语中,on= 部分应使用联接列名称和规则进行填充,如 on=(id)on=.(from_date

下面是Matt Dowle解释< code>roll=的一个更复杂的例子:为每一行查找特定值最近出现的时间

另一个相关示例:使用 data.table 进行左连接

 类似资料:
  • 我有两个结构相同的data.table。两个键列后跟许多数据列。数据列的数量可能会有所不同。我想将第二data.table的值添加到第一data.table.的相应行/列中 到目前为止,我的最佳选择如下: 请注意,nrow 和 ncol 以及 loc 和产品条目都是可变的,具体取决于源数据。 如果 DT2 中的每一行都与 DT1 中的一行匹配,则此方法有效,否则会产生意外的结果。有没有一种更严格/

  • 我正在使用Ingres 11.0 DB,不确定它是否在其他数据库引擎上具有相同的行为,但这里是它 它不会返回表1中的所有记录,但我使用的是左连接,它应该从T1返回aa记录,从t2只处理行,只返回1条记录 如果我将其中一个条件从where子句移动到join条件,它的开始将返回我所期望的结果 问题是为什么它不工作在哪里所有搜索条件在哪里子句,但工作时,我移动t2.id_number从哪里加入条件? 我

  • 当我添加一个左连接来获取外部表的计数时,它将我其他左连接表的总和值与计数相乘,我也不能在这里使用不同的总和,因为两个值可以是相同的:

  • 主要内容:Oracle LEFT JOIN子句简介,Oracle LEFT JOIN示例在本教程中,您将学习如何使用Oracle 子句来查询多个表中的数据。 Oracle LEFT JOIN子句简介 以下语句说明连接两个表和时的子句的语法: 在这个查询中,是左表,是右表。查询将表中的每一行与表中的行进行比较。如果和表中的一对行满足连接谓词,查询将组合两个表中行的列值,并将结果行记录包含在结果集中。 如果表中的行在表中没有找到匹配的行,则查询将会将SELECT子句中出现在表的每个列的值

  • LEFT OUTER JOIN 左外连接 [ ] 需求:查询所有分类,如果该分类下没有商品,则不显示该分类 [ ] 实现: SELECT `goods`.`id`, `goods`.`title`, `goods`.`price`, `goods`.`cate_id`, `cate`.`id`, `cate`, `cate.title` F

  • 我试图更多地理解滚动加入的工作方式,并有一些困惑,我希望有人能为我澄清这一点。举一个具体的例子: 我希望这会生成一个长的,其中滚动中的值: 另外,文档中说: 这使得看起来只有X中的东西应该返回,而正在执行的联接是内部联接,而不是外部联接。如果,但是中不存在特定的呢?再玩一点,我不明白列中有什么值。