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

han*_*ick 2 hash dictionary r function

我有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)
Run Code Online (Sandbox Code Playgroud)

我的问题是将每个完全相同的向量映射到一个整数,即我需要一个输入向量并产生整数的mappy函数. mappy(c(58431, 976854, 661294, 460685, 341123))=15, 例如.你知道如何以有效的方式做到这一点吗?

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

jos*_*ber 6

我假设你想在列表中的向量和整数之间进行双射.一种方法是从向量的字符表示中创建一个因子变量.让我们从代码的可重现版本开始(我将它变成一个更小的向量):

set.seed(144)
VECTORS <- replicate(1e2, sample(seq_len(1e6), 5), FALSE)
Run Code Online (Sandbox Code Playgroud)

现在,您可以从每个向量的字符表示创建一个因子变量:

fvar <- factor(sapply(VECTORS, paste, collapse=" "))
Run Code Online (Sandbox Code Playgroud)

现在我们在元素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
Run Code Online (Sandbox Code Playgroud)

如果你想将它们包装成很好的函数:

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
Run Code Online (Sandbox Code Playgroud)

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


Fra*_*ank 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
Run Code Online (Sandbox Code Playgroud)

评论正如@Roland所提到的,(a)1..1e6和(b)之间的所有 5个长度序列的1~1e5的不同数字是不可能的,所以我只是猜测这就是OP是之后.

当您...使用参数编写函数时,这意味着接受任意数量的未命名参数.在函数中,这些参数可以用...,但通常也可以用c(...)和来看list(...).在data.table中,.(...)是别名list(...).要查看编​​写函数的文档,请键入help.start()并单击"R语言定义".