簡體   English   中英

data.table:如何對一個鍵的兩個(數字)值進行二進制搜索:包括示例

[英]data.table: How to do binary search for two (numeric) values at one key: example included

示例數據:

library(data.table)
DT <- data.table(a = c(1, 3, 5, 9, 15), 
                 b = c("a", "c", "d", "e", "f"))

我想得到兩行,即a == 3 | a == 9 a == 3 | a == 9 ,即

# a b
# 3 c
# 9 e

我知道是否這樣做: DT[, a:=as.character(a)]然后setkey(DT, a)DT[c("3", "9")] ,我可以得到想要的結果。 但是我想知道,是否有其他方法可以在不事先將a更改為字符的情況下進行這種二進制搜索?

首先,在執行基於聯接/二進制搜索的子集之前,不必每次都轉換為字符列。 您可以使用J()並將整數/數字/字符/邏輯/ bit64 :: integer64矢量傳遞給它,如下所示:

DT[J(vec1, vec2, ...)]

其中, vec1將抵靠第一鍵列和匹配vec2靠在第二鍵列等。

不必為字符類型添加J()的事實是一項附加功能 ,只是為了方便起見。 因為整數/數字/邏輯向量已經具有這樣的含義DT[1]將返回第一行,所以我們無法為這些類型提供相同的快捷方式。 希望這能回答您的原始問題。

回到您的問題,使用值(3,9)子集a列,您可以使用data.table基於二進制搜索的子集來實現:

require(data.table)
setkey(DT, a)
DT[J(c(3,9))] ## alternatively DT[.(c(3,9))] in 1.9.4+
#    a b
# 1: 3 c
# 2: 9 e

有兩點需要注意,您可以使用data.table的二進制搜索功能快速子集化:

  • 它要求您對整個數據進行排序(這可能並不總是很理想)。
  • 在非常大的數據集上,重新安排內存中數據的時間可能很耗時(查找順序本身通常比移動數據便宜得多)。

為了解決這些問題並提供更好的功能,data.table在1.9.4中通過引入新的實驗功能 -在輔助鍵的幫助下自動建立索引來解決此問題。 Matt已在1.9.4中實現了這一點。

自動索引的作用是,如果尚不存在輔助鍵,則可以在data.table理解的表達式的首次運行(此刻)進行優化時,將創建輔助鍵。 它只是使用data.table的快速基數排序存儲此列的順序,並將其存儲為屬性。 setkey不同, setkey沒有數據的重新排序。 您也可以使用set2key()設置輔助密鑰。

首次運行它所花費的時間等於a)輔助鍵的時間(通常很小),以及b)查詢的時間。 從第二次開始,這只是查詢時間,使用二進制搜索可以快速進行。

如果用data.table現在可以理解的表達式查詢另一列,那么它將在該列首次運行時另外為該列設置一個輔助鍵。 等等...

兩種方法之間的速度不應有(明顯的)差異(完成setkeyset2key )。 請參見下面的示例。

輔助鍵的概念可以擴展到自動索引之外,也可以擴展到聯接。 這將加快data.table的連接速度。


這是一個例子。 我將使用1.9.5,因為Matt已經解決了自動索引編制中的一些錯誤。

require(data.table) ## 1.9.5+
set.seed(45L)
DT = data.table(x=sample(1e3, 5e7, TRUE))[, y := x]
setkey(DT, x)
set2key(DT, y)

請注意,在setkey(.) DT將通過引用重新排序。 但是set2key只會設置一個屬性,因此不會根據y的順序對數據進行重新排序。

x和y列相同(有意)。 讓我們同時測試:

system.time(DT[J(100L)])   ## on column x, 0.003 seconds
system.time(DT[y == 100L]) ## on column y, 0.003 seconds, uses secondary keys

identical(DT[J(100L)], DT[y==100L]) # [1] TRUE

矢量掃描需要多少時間?

options(datatable.auto.index = FALSE)
system.time(DT[y == 100L]) ## 0.428 seconds

您無需將其轉換為字符向量(盡管整數會更有意義)

 DT <- data.table(a = c(1, 3, 5, 9, 15), b = c("a", "c", "d", "e", "f"))
 setkey(DT, a)
 DT[J(c(3, 9))]

此外,如果您具有CRAN中的最新版本,則第二次在i中使用a將自動使用二進制搜索

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM