2015-10-11 67 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语言定义”。