2017-03-05 87 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