2017-03-05 86 views
1

我有一个包含文本字符串的矢量的数据框。我试图根据每个字符串是否包含在几个列表之一中,并将这些字符串分配给数据帧中的新矢量,将这些字符串重新编码为值(0,1,2,...)。例如, :R - 根据匹配到多个列表中的一个匹配矢量值

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”,根据是否向量[i]是包含在列表1或列表2,或项目list3:

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

我尝试过%的%的各种排列,但问题是“矢量”是非常长(数十万个元素),并且我所匹配的一些列表也相当长(10-30个元素)。我有这个工作的声明,但是极端慢。看着苔藓生长缓慢。

什么是R“窍门”,用于优化加速这样的复杂匹配场景?

回答

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]。加入使用i查找x中的行。 j是使用匹配行计算的一些值(这里,仅为i中的一列)。

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

+1

OMG,这方面的成效斐然!谢谢,弗兰克 - 你真的救了我的皮! 这绝对是我放入个人图书馆的一招。 – TPL