2015-10-11 106 views
2

我有100,000個5長度向量(列表向量),其元素從一百萬個值中選擇。以雙射方式將向量映射爲整數

# dictionary 
dictionary=seq(1:1e6) 

# generate 100,000 5-length vectors whose elements are chosen from dictionary 
VECTORS <- lapply(c(1:1e5), sample, x = dictionary, size =5) 

我的問題是每個完全相同的矢量映射到一個整數,即我需要,其輸入向量,併產生一個整數MAPPY功能。例如, mappy(c(58431, 976854, 661294, 460685, 341123))=15。你知道如何以有效的方式做到這一點?

輔助問題:如果我的向量長度不一樣會怎麼樣?

+4

沒有足夠的整數來映射'1e6^5'可能的向量。 – Roland

+1

看起來,像'匹配(矢量,獨特(矢量))'也許可能有幫助 –

回答

6

我假設你想在你的列表和整數中的向量之間進行雙向注入。一種方法是在矢量的字符表示之外創建因子變量。讓我們先從你的代碼的可重複的版本(我會讓它更小的向量):

set.seed(144) 
VECTORS <- replicate(1e2, sample(seq_len(1e6), 5), FALSE) 

現在你可以從每個向量的字符表示創建一個因子變量:

fvar <- factor(sapply(VECTORS, paste, collapse=" ")) 

現在我們有VECTORS元素和整數的字符串表示的雙射:

vec <- c(894025, 153892, 98596, 218401, 36616) # 15th element of VECTORS 
which(levels(fvar) == paste(vec, collapse=" ")) 
# [1] 90 
levels(fvar)[90] 
# [1] "894025 153892 98596 218401 36616" 
as.numeric(strsplit(levels(fvar)[90], " ")[[1]]) 
# [1] 894025 153892 98596 218401 36616 

如果你想將它們包裝成漂亮的功能:

id.from.vec <- function(vec) which(levels(fvar) == paste(vec, collapse=" ")) 
id.from.vec(c(894025, 153892, 98596, 218401, 36616)) 
# [1] 90 

vec.from.id <- function(id) as.numeric(strsplit(levels(fvar)[id], " ")[[1]]) 
vec.from.id(90) 
# [1] 894025 153892 98596 218401 36616 

請注意,即使矢量長度不同,它也可以使用。

6

甲鍵控data.table具有良好的查找性能:

library(data.table) 
set.seed(1) 
VECTORS <- lapply(seq(1e5), sample, x = 1e6, size = 5) 
VECmap <- setkey(rbindlist(lapply(unique(VECTORS), as.list)))[, ID := .I] 

#    V1  V2  V3  V4  V5  ID 
#  1:  13 897309 366563 678873 6571  1 
#  2:  15 557977 640484 732531 848939  2 
#  3:  48 18120 911805 188728 805726  3 
#  4:  48 830301 862433 506297 877432  4 
#  5:  52 873436 824165 86251 576173  5 
#  ---           
# 99996: 999911 583599 803402 240910 931996 99996 
# 99997: 999931 146505 287431 180259 230904 99997 
# 99998: 999937 175888 266336 874987 982951 99998 
# 99999: 999950 960139 455084 586956 875504 99999 
# 100000: 999993 191750 258982 518519 78087 100000 

mapVEC <- function(...) VECmap[.(...)]$ID 
mapID <- function(id) unlist(VECmap[ID==id,!"ID",with=FALSE], use.names=FALSE) 

# example usage 
mapVEC(52, 873436, 824165, 86251, 576173) 
# 5 
mapID(5) 
# 52 873436 824165 86251 576173 

評論如@Roland中,(a)1..1e6和(b)所有 5-長度之間的雙射提到從1..1e5開始的不同數字的序列是不可能的,所以我只是猜測這就是OP的結果。

當你寫與...一個函數作爲參數,這意味着未命名的參數的任意數量的被接受。在函數內部,這些參數可以用...來引用,但是通常也可以用c(...)list(...)來看。在data.table中,.(...)list(...)的別名。要查看寫入函數的文檔,請鍵入help.start()並單擊「R語言定義」。