以双射方式将矢量映射为整数

时间:2015-10-11 13:01:07

标签: r function dictionary hash

我有100,000个5长度向量(下面的列表VECTORS),其元素是从一百万个值中选择的。

# 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。你知道如何以有效的方式做到这一点吗?

附属问题:如果我的载体长度不再相同怎么办?

2 个答案:

答案 0 :(得分: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

请注意,即使向量长度不同,这也可以开箱即用。

答案 1 :(得分: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()并单击“&#34; R语言定义”。&#34;