带有 all=True 的 merge.data.table 引入了 NA 行。它是不是正确?

Posted

技术标签:

【中文标题】带有 all=True 的 merge.data.table 引入了 NA 行。它是不是正确?【英文标题】:merge.data.table with all=True introduces NA row. Is this correct?带有 all=True 的 merge.data.table 引入了 NA 行。它是否正确? 【发布时间】:2013-03-12 01:38:03 【问题描述】:

在填充的 data.table 和另一个空的 data.table 之间进行合并会在结果 data.table 中引入一个 NA 行:

a = data.table(c=c(1,2),key='c')
b = data.table(c=3,key='c')
b=b[c!=3]
b
# Empty data.table (0 rows) of 1 col: c
merge(a,b,all=T)
#     c
# 1: NA
# 2:  1
# 3:  2

为什么?我希望它只返回 data.table a 的行,就像它对 merge.data.frame 所做的那样:

> merge.data.frame(a,b,all=T,by='c')
#  c
#1 1
#2 2

【问题讨论】:

所以你想合并a和一个空的数据表b。为什么你以这种不寻常的方式介绍b?为什么不使用b=data.table() @user974514:我只是想重现问题,因为它出现在我的代码中。通常,我的代码中的data.table 已填充,但有时不会填充,在我的情况下,表是键控的,合并自然会使用这些键。一个简单的data.table() 并不能完全重现我遇到的问题。 @user974514,这将给出一个 NULL data.table(0 行和列)并且不会有“key”列。所以,合并是不可能的。 @Arun,我不这么认为。我对data.frame 做了同样的事情,结果是预期的结果:一个新的data.frame,只有填充的行。 【参考方案1】:

问题中的示例过于简单,无法显示问题,因此造成了混乱和讨论。使用两个单列 data.tables 不足以显示 merge 的作用!

这是一个更好的例子:

> a = data.table(P=1:2,Q=3:4,key='P')
> b = data.table(P=2:3,R=5:6,key='P')
> a
   P Q
1: 1 3
2: 2 4
> b
   P R
1: 2 5
2: 3 6
> merge(a,b)  # correct
   P Q R
1: 2 4 5
> merge(a,b,all=TRUE)  # correct.  
   P  Q  R
1: 1  3 NA
2: 2  4  5
3: 3 NA  6
> merge(a,b[0],all=TRUE)  # incorrect result when y is empty, agreed
    P  Q  R
1: NA NA NA
2: NA NA NA
3:  1  3 NA
4:  2  4 NA
> merge.data.frame(a,b[0],all=TRUE)  # correct
  P Q  R
1 1 3 NA
2 2 4 NA

Ricardo 对此进行了深入研究,并在 v1.8.9 中对其进行了修复。来自新闻:

当 y 为空并且 all.y=TRUE(或 all=TRUE),#2633。谢谢 给 Vinicius Almendra 报告。已添加测试。

【讨论】:

【参考方案2】:

所有:逻辑; all = TRUE 是保存设置 all.x = TRUE 和 all.y = TRUE 的简写。

all.x:逻辑;如果为 TRUE,那么额外的行将被添加到输出中,每一行对应一个 x 在 y 中没有匹配的行。这些行将在这些列中包含“NA” 通常用来自 y 的值填充。默认为 FALSE,因此只有行 来自 x 和 y 的数据都包含在输出中。

all.y:逻辑;类似于上面的 all.x。

这取自 data.table documentation。有关更多信息,请查看那里的 merge 函数的参数描述。

我认为这回答了你的问题。

【讨论】:

也许你可以试试ifelse(dim(b)[1]==0, merge(a,b,all.x=T), merge(a,b,all.y=T)) 或类似的东西 本文档与merge.data.frame 相同,但行为不同。我不明白为什么带有空表的完全外连接应该添加一个 NA 行。【参考方案3】:

假设您以自己的方式定义了abrbind(a,b) 的简单用法将只返回 a 的行。

但是,如果您想将 NULL 数据表 b 与其他一些非空数据表 a 合并,则有不同的方法。当我不得不在不同的循环中合并不同的数据表时,我遇到了类似的问题。我使用了这个解决方法。

  #some loop that returns data.table named a
  #another loop starts
  if(all.equal(a,b<-data.table())==TRUE)
  b<-a
  next
  
  merge(a,b,c("Factor1","Factor2"))

这对我有帮助,也许对你也有帮助。

【讨论】:

对不起,我不太明白你的 if 语句。如果a 是维度0 by 0data.table(如b),则将b 分配给a。为什么?而且您没有使用copy(a)。这将只是通过引用分配,而不是将 a 复制到 b。我不明白。 假设您有一个循环来填充 data.table a。所以它不是空的。但在循环结束时,您希望将其与其他数据表 b 合并,该表在第一次迭代中可以为空,但在第二次迭代中变为非空。这就是此解决方法要解决的问题。 投反对票来自我,如果您能解释(或编辑),我很乐意投赞成票)。 感谢您的回复。现在说得通了。但它没有回答 OP 的问题,因为 data.table 不是 0 行和列,但只有 0 行和 1 列. 对于OP的问题,我推荐使用rbind(a,b)。正如 OP 要求的那样,输出将只有 a 行。【参考方案4】:

这是意料之中的,因为merge.data.frame all=Tfull outer join,所以你得到两个表的所有键见about merge

【讨论】:

b 有一个空键(无行),与值为 NA 的键不同。 您可能发现了一个错误,因为这是一个非常不寻常的情况,您可以在数据表列表中发布吗? 谢谢。我刚刚提交了它和我发现的另一个错误,也与空 data.table 的... table b not 有一个空键。 tables() 表示键设置为列c 不知道为什么我们还在谈论它,data.table 应该复制 data.frame 行为,这是一个错误,让我们关闭广告继续...

以上是关于带有 all=True 的 merge.data.table 引入了 NA 行。它是不是正确?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 all() 为空的可迭代对象返回 True? [复制]

如何用 NA 以外的值填充 merge(..., all = TRUE, ...) 中的缺失值?

如何使用 facet 和 margin=TRUE 更改 ggplot 中的 strip.text 标签

为啥 Python 内置的“all”函数为空的可迭代对象返回 True?

为啥 Enumerable.All 对空序列返回 true? [复制]

为啥在ruby中,[].all?i i==1 的结果为true?