data.table笛卡尔加入合法连接的警告

 MichaelZhu 发布于 2022-12-04 04:03

我很抱歉提前发帖混淆了几个问题.如果不合适,请编辑或建议我应该做什么.我正在练习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=TRUEdata.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 个回答
  • 问题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].何时xi两者共享一个列名并将在连接结果中,这些列都i.添加了一个前缀.它是相同的前缀,也允许您访问i列中的j两个列,xi在表单x[i, j]或操作中共享列名x[i, j, by=.EACHI].

    加入时,您可以将名称更改为您喜欢的任何名称.在这里,你可以改变position.xposition.y有:

    dtMoveA[dtMoveB, .(RobotID, Position.x=Position, Position.y=i.Position,
                     AbsDistance = abs(Position - i.Position)), allow.cartesian=TRUE]
    

    HTH


    PS:如果您有任何建议,请随时在此处添加FR .请在执行此操作之前查看发布指南.

    2022-12-11 03:09 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有