我很抱歉提前发帖混淆了几个问题.如果不合适,请编辑或建议我应该做什么.我正在练习data.table join,这是一个想象的场景:
"两个机器人,每个机器人在MovementA有4个位置,在MovementB有4个位置.要解决的问题:对于每个机器人,从MoveA到MoveB,有4x4个可能的位置对找到最短距离的4对"
数据设置
library(data.table) set.seed(20141220) dtMoveA = data.table(RobotID = rep(1:2, each=4), Position=sample(1:20, 8)) dtMoveB = data.table(RobotID = rep(1:2, each=4), Position=sample(1:20, 8)) # Review Data rbind(cbind(Movement="Move-A", dtMoveA), cbind(Movement="Move-B", dtMoveB)) Movement RobotID Position 1: Move-A 1 18 2: Move-A 1 20 3: Move-A 1 15 4: Move-A 1 8 5: Move-A 2 13 6: Move-A 2 2 7: Move-A 2 9 8: Move-A 2 12 9: Move-B 1 18 10: Move-B 1 14 11: Move-B 1 13 12: Move-B 1 17 13: Move-B 2 5 14: Move-B 2 16 15: Move-B 2 20 16: Move-B 2 3
解决方案1(使用dplyr)
library(dplyr) dtMoveA %>% inner_join(dtMoveB, by="RobotID") %>% mutate(AbsDistance = abs(Position.x - Position.y)) %>% group_by(RobotID, Position.x) %>% filter(AbsDistance == min(AbsDistance)) %>% arrange(RobotID, Position.x) RobotID Position.x Position.y AbsDistance 1 1 8 13 5 2 1 15 14 1 3 1 18 18 0 4 1 20 18 2 5 2 2 3 1 6 2 9 5 4 7 2 12 16 4 8 2 13 16 3
(尝试)解决方案2(使用data.table)
setkey(dtMoveA, RobotID) setkey(dtMoveB, RobotID) dtMoveA[dtMoveB, .(RobotID, Position, i.Position, AbsDistance = abs(Position - i.Position)), allow.cartesian=TRUE ] [, MinDistance := min(AbsDistance), by=list(RobotID, Position) ] [ AbsDistance == MinDistance, .(Position, i.Position, AbsDistance), by=RobotID ] [ order(RobotID, Position)] RobotID Position i.Position AbsDistance 1: 1 8 13 5 2: 1 15 14 1 3: 1 18 18 0 4: 1 20 18 2 5: 2 2 3 1 6: 2 9 5 4 7: 2 12 16 4 8: 2 13 16 3
问题1您能否通过data.table art的良好实践来纠正我的Solution2?
没有参数allow.cartesian=TRUE
data.table的问题2警告
"连接结果为32行;超过8 =最大值(nrow(x),nrow(i)).检查i中的重复键值,每个键值都加入到同一组中x一遍又一遍.如果没关系,请尝试包含j
并删除by
(by-without-by),以便为每个组运行j以避免大量分配.如果您确定要继续,请使用allow.cartesian = TRUE重新运行"
它真的是笛卡尔积吗?这里只对公共密钥值进行连接,这只是数据的巧合,产生了很大的连接结果.
问题3 dtMoveA和dtMoveB具有相同的列名.数据表连接通过将名称更改为来区分i.Position
."i"前缀是硬编码的吗?我想i.ColumnName总是适用于X [Y]连接表达式中的Y成员.
在此先感谢您的帮助.
问题1:
看起来很棒!但是内连接的等价物也是要添加的nomatch=0L
.否则你也会得到所有的行dtMoveB
.我们不能在by=.EACHI
这里使用AFAICT.
阅读此回答和本评论中链接的答案,以了解其目的allow.cartesian = TRUE
.
问题2:从?data.table
以下条目下allow.cartesian
:
FALSE
防止会导致多max(nrow(x), nrow(i))
行的连接.这通常是由i
连接列中的重复值引起的,每个连接列都x
反复连接到同一个组:错误指定的连接.通常这不是预期的,需要更改连接.在这种情况下,"笛卡儿"这个词被宽泛地使用了.传统的笛卡尔连接(故意)很难在data.table中实现:其中每一行都
i
连接到x
(nrow(x) * nrow(i)
行结果)中的每一行.'笛卡儿'只是意味着"大量乘法".
这回答了你的问题了吗?
问题3:
是.联接是形式x[i]
.何时x
和i
两者共享一个列名并将在连接结果中,这些列都i.
添加了一个前缀.它是相同的前缀,也允许您访问i
列中的j
两个列,x
并i
在表单x[i, j]
或操作中共享列名x[i, j, by=.EACHI]
.
加入时,您可以将名称更改为您喜欢的任何名称.在这里,你可以改变position.x
和position.y
有:
dtMoveA[dtMoveB, .(RobotID, Position.x=Position, Position.y=i.Position, AbsDistance = abs(Position - i.Position)), allow.cartesian=TRUE]
HTH
PS:如果您有任何建议,请随时在此处添加FR .请在执行此操作之前查看发布指南.