在 data.table 中查找匹配项的行索引(我可以二分查找吗?)
Find row indices of matches in data.table (can I binary search?)
这似乎是一个很明显的问题,但我觉得我做错了。我有一个字符串向量,我只想在 data.table 中找到匹配的行索引。 data.table 由我要匹配的列作为键,因此,我认为我应该能够使用二进制搜索来查找匹配的索引。
示例如下:
在这里,我有一个 data.table,由列 c2
和一个字符串向量 new_dat
键控,我想为其找到行索引。
library(data.table)
## Example data, a keyed data.table
dat <- data.table(c1=1:10, c2=letters[1:10], key='c2')
## Match at some indices (keyed column so should be binary search?)
new_dat <- c('d', 'j')
## This doesn't feel right -- I don't think this is taking advantage of the
## data.table ordering at all
## Tried some dumb stuff like dat[match(new_dat, c2, 0L), .I]
dat[match(new_dat, c2, 0L), ] # only want the index of the matches
# c1 c2
# 1: 4 d
# 2: 10 j
## So, this is the desired result,
## but this is just doing ordinary linear search (I say w/o actually looking at the code)
match(new_dat, dat[['c2']], 0L)
# [1] 4 10
艾迪德
我刚刚意识到我可以做到,
dat[, ind := 1:.N][match(new_dat, c2, 0L), ind]
得到索引,还是没有解决我想描述的问题。
为了查找行索引(而不是使用 by
参数分组),您可以在执行二进制连接时指定 which = TRUE
options(datatable.verbose = TRUE) # Setting to TRUE so we can see the binary join being triggered
dat[new_dat, which = TRUE]
# Starting bmerge ...done in 0 secs <~~ binary join triggered
# [1] 4 10
(这也可以在不创建 c1
的情况下工作,因为它根本不使用该列)
而且,如果你只是想执行一个普通的二进制连接并查看所有列中的所有值,你不需要使用 match
或创建索引,只需执行
dat[new_dat]
# Starting bmerge ...done in 0 secs <~~ binary join triggered
# c1 c2
# 1: 4 d
# 2: 10 j
一般来说,只要你的数据是keyed的(或者你使用on
参数为了加入)和 new_dat
是不class integer
或 numeric
, data.table
会自动触发二进制连接,即使 new_dat
被传递给第 i
个参数 没有被包装成.
或J
。但是,如果 new_dat
是上述 class 之一,data.table
将尝试执行 行索引 。因此,您需要使用 dat[.(new_dat), which = TRUE]
或 dat[J(new_dat), which = TRUE]
来强制 bmerge
而不是行索引。
这似乎是一个很明显的问题,但我觉得我做错了。我有一个字符串向量,我只想在 data.table 中找到匹配的行索引。 data.table 由我要匹配的列作为键,因此,我认为我应该能够使用二进制搜索来查找匹配的索引。
示例如下:
在这里,我有一个 data.table,由列 c2
和一个字符串向量 new_dat
键控,我想为其找到行索引。
library(data.table)
## Example data, a keyed data.table
dat <- data.table(c1=1:10, c2=letters[1:10], key='c2')
## Match at some indices (keyed column so should be binary search?)
new_dat <- c('d', 'j')
## This doesn't feel right -- I don't think this is taking advantage of the
## data.table ordering at all
## Tried some dumb stuff like dat[match(new_dat, c2, 0L), .I]
dat[match(new_dat, c2, 0L), ] # only want the index of the matches
# c1 c2
# 1: 4 d
# 2: 10 j
## So, this is the desired result,
## but this is just doing ordinary linear search (I say w/o actually looking at the code)
match(new_dat, dat[['c2']], 0L)
# [1] 4 10
艾迪德
我刚刚意识到我可以做到,
dat[, ind := 1:.N][match(new_dat, c2, 0L), ind]
得到索引,还是没有解决我想描述的问题。
为了查找行索引(而不是使用 by
参数分组),您可以在执行二进制连接时指定 which = TRUE
options(datatable.verbose = TRUE) # Setting to TRUE so we can see the binary join being triggered
dat[new_dat, which = TRUE]
# Starting bmerge ...done in 0 secs <~~ binary join triggered
# [1] 4 10
(这也可以在不创建 c1
的情况下工作,因为它根本不使用该列)
而且,如果你只是想执行一个普通的二进制连接并查看所有列中的所有值,你不需要使用 match
或创建索引,只需执行
dat[new_dat]
# Starting bmerge ...done in 0 secs <~~ binary join triggered
# c1 c2
# 1: 4 d
# 2: 10 j
一般来说,只要你的数据是keyed的(或者你使用on
参数为了加入)和 new_dat
是不class integer
或 numeric
, data.table
会自动触发二进制连接,即使 new_dat
被传递给第 i
个参数 没有被包装成.
或J
。但是,如果 new_dat
是上述 class 之一,data.table
将尝试执行 行索引 。因此,您需要使用 dat[.(new_dat), which = TRUE]
或 dat[J(new_dat), which = TRUE]
来强制 bmerge
而不是行索引。