我正在尝试从data.frame
转换为data.table
,并且需要对我尝试在单个列上执行的某些逻辑索引提供一些建议。这是我的一张桌子:
places <- data.table(name=c('Brisbane', 'Sydney', 'Auckland',
'New Zealand', 'Australia'),
search=c('Brisbane AU Australia',
'Sydney AU Australia',
'Auckland NZ New Zealand',
'NZ New Zealand',
'AU Australia'))
# name search
# 1: Brisbane Brisbane AU Australia
# 2: Sydney Sydney AU Australia
# 3: Auckland Auckland NZ New Zealand
# 4: New Zealand NZ New Zealand
# 5: Australia AU Australia
setkey(places, search)
我想提取search
列与列表中所有字词匹配的行,如下所示:
words <- c('AU', 'Brisbane')
hits <- places
for (w in words) {
hits <- hits[search %like% w]
}
# I end up with the 'Brisbane AU Australia' row.
我有一个问题:
还有更多data.table
- 方法吗?在我看来,每次存储hits
似乎是data.frame
这样做的方式。
这需要注意我最终想要使用agrep
而不是grep
/ %like%
:
words <- c('AU', 'Bisbane') # note the mis-spelling
hits <- places
for (w in words) {
hits <- hits[agrep(w, search)]
}
我觉得这并没有充分利用data.table
的功能,并希望能够如何修改代码。
修改
我想要for循环因为places
非常大,我只想找到与 all 匹配的行。因此,我只需要在结果中搜索下一个单词的最后一个单词(即,连续细化结果)。
在data.table
介绍中谈到“二进制扫描”与“矢量扫描”(即“坏方法”为DT[DT$x == "R" & DT$y == "h"]
,“好方法”是setkey(DT, x, y); DT[J("R", "h")]
我只是想知道如果有某种方法我可以在这里应用这种方法。
答案 0 :(得分:3)
Mathematical.coffee,正如我在评论中提到的,你不能通过将一列(或多列)设置为键列来“部分匹配”。也就是说,在data.table
个地方,您已将“搜索”列设置为键列。在这里,您可以通过使用data.table's
二进制搜索(而不是矢量扫描子集)来快速子集:
places["Brisbane AU Australia"] # binary search when "search" column is key'd
# is faster compared to:
places[search == "Brisbane AU Australia"] # vector scan
但在你的情况下,你需要:
places["AU"]
使所有行在键列中具有“AU”的部分匹配。这是不可能的(虽然这当然是一个非常有趣的功能)。
如果您自己搜索的substring
不包含不匹配,则可以尝试将搜索字符串拆分为单独的列。也就是说,如果列search
分为包含Brisbane
,AU
和Australia
的三列,那么您可以设置{的{em>键 {1}}包含data.table
和AU
的列。然后,您可以查询您提到的方式:
Brisbane
答案 1 :(得分:0)
您可以对agrep
函数进行矢量化以避免循环。
请注意,agrep2
的结果是一个列表,因此unlist
调用
words <- c("Bisbane", "NZ")
agrep2 <- Vectorize(agrep, vectorize.args = "pattern")
places[unlist(agrep2(words, search))]
## name search
## 1: Brisbane Brisbane AU Australia
## 2: Auckland Auckland NZ New Zealand
## 3: New Zealand NZ New Zealand