【问题标题】:How to create an empty datatable with columns names and then append datatables to it?如何使用列名创建一个空数据表,然后将数据表附加到它?
【发布时间】:2016-09-19 11:20:38
【问题描述】:

首先我想创建一个带有列名的空数据表,但它失败了:

data <- data.table(va, vb, vc)

> Error in data.table(va, vb, vc) : object 'va' not found

其次,我想将数据表附加到它,但它也失败了:

data2 <- data.table(va=c(-1,0,1), vb=c(-1,0,1), vc=c(-1,0,1))
data2
   va vb vc
1: -1 -1 -1
2:  0  0  0
3:  1  1  1
merge(data2,data2)

> Error in merge.data.table(data2, data2) : 
      Can not match keys in x and y to automatically determine appropriate `by` parameter. Please set `by` value explicitly.

显然该函数无法识别具有两个相同数据表的by 参数。有什么想法吗?

【问题讨论】:

  • "object va" not found 是因为 R 假定它是一个变量名,并且您的工作区中没有名为 va的现有变量
  • 创建一个空的 data.table 使用(假设所有列都是数字):data=data.table(va=numeric(), vb=numeric(), vc=numeric())
  • 在循环中动态增长事物(这听起来像是你正在做的事情)在 R 中是个坏主意。
  • 这个问题已经过时了,merge(data2,data2) 在 data.table v1.11.x 中默认所有(共享)键就好了。我猜这在 v1.9.6 (2016) 中没有实现。
  • @tamarad R Inferno 的第 2 章(在此免费 burns-stat.com/pages/Tutor/R_inferno.pdf)是人们通常指出的,其中提到“碎片化内存”和缓慢作为副作用。这适用于向量、数组和表格。我认为一个例外是增加列表是可以的,如 cmets 中所述:stackoverflow.com/questions/14801035/…

标签: r merge data.table


【解决方案1】:

创建一个空的data.table 使用(假设所有列都是数字):

library(data.table)    
data <- data.table(va=numeric(), vb=numeric(), vc=numeric())
data

导致:

> data
Empty data.table (0 rows) of 3 cols: va,vb,vc

对所有列进行自联接,请使用(即使结果相同 ;-):

data2 <- data.table(va=c(-1,0,1), vb=c(-1,0,1), vc=c(-1,0,1))
data2
merge(data2, data2,by=names(data2))

您必须指定by 参数的原因是merge 的记录语义:

作者:

要合并的 x 和 y 中的共享列名向量。这个默认 到两个表之间的共享键列。如果 y 没有密钥 列,默认为 x 的键。

由于您没有设置任何键,因此用于合并数据表的“连接”列不清楚。

如果您省略 by 参数(如上文所述,采用共享键列),则没有隐含的“使用所有列”语义。

要将 data.table 的所有行追加到另一个你使用rbind(“行绑定”)而不是merge

data3 <- rbind(data2, data2)
data3

结果:

> data3
   va vb vc
1: -1 -1 -1
2:  0  0  0
3:  1  1  1
4: -1 -1 -1
5:  0  0  0
6:  1  1  1

【讨论】:

  • 在 1.11.x 中,merge 现在尽可能使用共享键列。 “如果省略merge(..., by) 参数,则没有隐含的“使用所有列”语义” 不再为真;我猜它没有在 2016 年(v1.9.6)实施。你能纠正你的答案吗?
【解决方案2】:

要创建一个空的data.table,可以从一个空矩阵开始:

library(data.table)
data <- setNames(data.table(matrix(nrow = 0, ncol = 3)), c("va", "vb", "vc"))
data
Empty data.table (0 rows) of 3 cols: va,vb,vc

然后您可以使用rbindlist 将新的data.table 附加到它:

data2=data.table(va=c(-1,0,1), vb=c(-1,0,1), vc=c(-1,0,1))
data2
   va vb vc
1: -1 -1 -1
2:  0  0  0
3:  1  1  1
rbindlist(list(data, data2))
   va vb vc
1: -1 -1 -1
2:  0  0  0
3:  1  1  1

或者更简单,以下方法也可以:

data <- data.table()
data <- rbindlist(list(data, data2))
data
   va vb vc
1: -1 -1 -1
2:  0  0  0
3:  1  1  1

【讨论】:

  • 应该是公认的答案...在这方面有很大的灵活性...
  • 要使其成为一个完整的data.table 方式,而不是使用setnames 而不是setNames
【解决方案3】:

另一种创建具有已定义列名但无需定义数据类型的空 data.table 的方法:

data <- data.table(1)[,`:=`(c("va", "vb", "vc"),NA)][,V1:=NULL][.0]

执行以下操作

  1. data.table(1):创建一个非NULL data.table,您可以在其中添加列
    • 有一列V1 和一行。价值1
    • 您可以使用任何值(NULL 除外)代替1
  2. [,`:=`(c("va", "vb", "vc"),NA)]:添加列vavbvc
    • 现在有四列(以V1 开头)和一行。价值1,NA,NA,NA
    • 任何非NULL 值都可以替换为 NA
  3. [,V1:=NULL]:删除V1
  4. [.0]: 返回一个空白行
    • 您实际上可以使用 [.n] 其中 n 是任意的 整数。

如果你不喜欢[.0]的黑魔法你也可以使用

data <- data.table(1)[,`:=`(c("va", "vb", "vc"),NA)][,V1:=NULL][!is.na(va)]

【讨论】:

  • 有趣的黑魔法。你是怎么想到.0的?以前没见过
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-25
  • 1970-01-01
  • 2020-07-03
  • 2020-05-14
  • 2020-09-05
  • 2019-02-28
相关资源
最近更新 更多