R - 根据与多个列表之一的匹配将值赋给向量

时间:2017-03-05 02:51:38

标签: r performance

我有一个数据框,其中包含一个包含文本字符串的向量。我试图根据每个字符串是否包含在几个列表中的一个列表中,将这些字符串重新编码为值(0,1,2,...),并将其分配给数据框中的新向量

例如:

vector = c( "A", "B", "C", "D", "E")
list1 = c("B", "G", "P", "Z")
list2 = c("A", "E", "M", "Q")
list3 = everything not in list1 or list2

新向量应分配" 0"," 1"或" 2"根据vector [i]是否包含在list1,或list 2,或list3:

new_vector = (2, 1, 3, 3, 2)

我尝试了%in%的各种排列,但问题在于" vector"非常长(数十万个元素),我匹配的一些列表也相当长(10-30个元素)。我的声明有效,但非常慢。看着苔藓变得有点慢。

什么是R"技巧"为了最佳地加速像这样的复杂匹配场景?

1 个答案:

答案 0 :(得分:2)

首先,您应该将列表存储在一个对象中,而不是编号名称:

L = list(list1, list2)

然后你可以使用data.table进行相当快速的匹配:

library(data.table)
LDT = rbindlist(lapply(L, data.table), idcol = TRUE)
vDT = data.table(v = vector)

vDT[, id := LDT[vDT, on=.(V1 = v), .id]]

#    v id
# 1: A  2
# 2: B  1
# 3: C NA
# 4: D NA
# 5: E  2

无需为“不在其他列表中的所有内容”创建列表。它可以被赋予NA,如此处所示。

如果你的名单没有脱节,这会以奇怪的方式打破,所以你可能想设置一个规则来停止,如果是这样的话:

stopifnot( !anyDuplicated(LDT[, "V1"]) )

工作原理

LDT和vDT是表格,连接的语法是x[i,on=,j]。联接使用ix中查找行。 j是使用匹配行计算的值(此处只是i中的一列)。

要分配列,请使用j这样的colname := expression参数。有关详细信息,请参阅the website