Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/81.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R 仅按2列键的第2列对data.table进行子集设置,使用二进制搜索而不是向量扫描_R_Data.table - Fatal编程技术网

R 仅按2列键的第2列对data.table进行子集设置,使用二进制搜索而不是向量扫描

R 仅按2列键的第2列对data.table进行子集设置,使用二进制搜索而不是向量扫描,r,data.table,R,Data.table,我最近在data.table中发现了二进制搜索。如果表格按多个键排序,是否可以仅按第二个键进行搜索 DT = data.table(x=sample(letters,1e7,T),y=sample(1:25,1e7,T),rnorm(1e7)) setkey(DT,x,y) #R> DT[J('x')] # x y V3 # 1: x 1 0.89109 # 2: x 1 -2.01457 # --- #3

我最近在
data.table
中发现了二进制搜索。如果表格按多个键排序,是否可以仅按第二个键进行搜索

DT = data.table(x=sample(letters,1e7,T),y=sample(1:25,1e7,T),rnorm(1e7))
setkey(DT,x,y)
#R> DT[J('x')]
#        x  y       V3
#     1: x  1  0.89109
#     2: x  1 -2.01457
#    ---              
#384922: x 25  0.09676
#384923: x 25  0.25168
#R> DT[J('x',3)]
#       x y       V3
#    1: x 3 -0.88165
#    2: x 3  1.51028
#   ---             
#15383: x 3 -1.62218
#15384: x 3 -0.63601
编辑:感谢@Arun

R> system.time(DT[J(unique(x), 25)])
   user  system elapsed 
  0.220   0.068   0.288 
R> system.time(DT[y==25])
   user  system elapsed 
  0.268   0.092   0.359

是的,您可以将所有值传递给第一个键值,并将第二个键的特定值传递给子集

DT[J(unique(x), 25), nomatch=0]
如果需要在第二个键中按多个值进行子集划分(例如,相当于
DT[y%in%25:24]
),则更通用的解决方案是使用
CJ

DT[CJ(unique(x), 25:24), nomatch=0]
默认情况下,
CJ
会对列进行排序,并为所有列设置键,这意味着结果也会被排序。如果不需要这样做,则应使用
sorted=FALSE

DT[CJ(unique(x), 25:24, sorted=FALSE), nomatch=0]
还有一个功能请求,要求将来向
data.table
添加辅助键。我相信计划是添加一个新函数
set2key

还有
merge
,它有一个
数据表的方法。它为您在其中构建辅助密钥,因此应该比基本合并更快。请参见
?merge.data.table

基于我编写的以下函数:

create_index = function(dt, ..., verbose = getOption("datatable.verbose")) {
  cols = data.table:::getdots()
  res = dt[, cols, with=FALSE]
  res[, i:=1:nrow(dt)]
  setkeyv(res, cols, verbose = verbose)
}

JI = function(index, ...) {
  index[J(...),i]$i
}
以下是我的系统上DT较大(1e8行)的结果:

系统时间(DT[J(“c”)) 用户系统运行时间 0.168 0.136 0.306 >系统时间(DT[J(唯一(x),25)]) 用户系统运行时间 2.472 1.508 3.980 >系统时间(DT[y==25]) 用户系统运行时间 4.532 2.149 6.674 >系统时间(IDX_y系统时间(DT[JI(IDX_y,25)]) 用户系统运行时间 0.512 0.320 0.831

如果您多次使用索引,它是值得的。

谢谢,与通常的数据相比,它看起来有点低效。表性能,虽然比R向量搜索更好…是的,我想不出更好的方法。但我不认为它一般是打算这样使用的。例如,如果您检查,
DF[DF$x==“a”&DF$y==“25”
DT[J(“a”,25)]
你会看到区别的。当然,但是你必须再次排序…如果我们想排序的话,任何东西都可以。
DF[DF$x==“a”| DF$y==“25”,]
(或者代替和)@Arun已经在
nomatch=0
中编辑过了。这是需要的,对吧?以前没有发现过。@MatthewDowle我不知道哪种方法会更好(为了提高速度和/或增加功能)但是J中的
命名列可以定义要使用的键
将是一个非常方便且功能强大的选项,再次感谢您的
数据表
!谢谢。我已经扩展了第n个键的功能:现在在
Rdatatable
Github页面中的其中一个键中介绍了这一功能。
> system.time(DT[J("c")])
   user  system elapsed 
  0.168   0.136   0.306 

> system.time(DT[J(unique(x), 25)])
   user  system elapsed 
  2.472   1.508   3.980 
> system.time(DT[y==25])
   user  system elapsed 
  4.532   2.149   6.674 

> system.time(IDX_y <- create_index(DT, y))
   user  system elapsed 
  3.076   2.428   5.503 
> system.time(DT[JI(IDX_y, 25)])
   user  system elapsed 
  0.512   0.320   0.831