在r中的大数据表中查找大字符串列表的最快方法

时间:2015-09-16 12:30:54

标签: r

我有一个大约15.000个用户ID的列表,

> head(ID_data)
[1] "A01Y" "AC43" "BBN5" "JK45" "NT66" "WC44"

和一个包含3列和大约100.000行的表作为data.table:

> head(USER_data)
              V1                    V2                 V3
1:             0                  John               John
2:          A01Y        Martin 3311290               
3: Peter Johnson            Peter JK45                  x 
4:             1        wc44@email.com     wc44@email.com         
5:            NA                     x          
6:        419223    Christian 21221140     ac43@email.com

我想知道在3列中的某一列中包含用户ID的行的行索引。

在上面的示例中,代码应该找到第2,3,4和6行,因为它们在3列中的一列或多列中的某处包含“A01Y”,“JK45”,“WC44”和“AC43”。 / p>

主要问题是数据量很大。

我试过粘贴“|”在ID和使用grep之间搜索“A01Y | JK45”等:

toMatch <- paste(ID_data,collapse="|")
V1.matches <- grep(toMatch, USER_data$V1, ignore.case=TRUE)
V2.matches <- grep(toMatch, USER_data$V2, ignore.case=TRUE)
V3.matches <- grep(toMatch, USER_data$V3, ignore.case=TRUE)

但是grep只能采用大约2.500 ID的搜索模式,因此我必须以2500块的块来查看ID。这需要大约15分钟来计算。

我也尝试过使用strapplyc,它可以采用大约9.999 ID的搜索模式。

有没有更快的方法来查找行索引?

我正在考虑使用sqldf()并执行类似

的操作
sqldf("SELECT * FROM USER_data, ID_data WHERE USER_data LIKE '%'+ID_data+'%'")

但我不确定该怎么做。

提前感谢任何建议。

1 个答案:

答案 0 :(得分:0)

不确定这是否足够快,但我之前已经完成了很多行和ID。我花了一些时间,但不需要在块中处理ID。

# list of ids
IDs = c("A01Y", "AC43", "BBN5", "JK45", "NT66", "WC44")

# example dataframe
dt =  data.frame(V1 = c("Christian 21223456","x", "wc44@email.com"),
                 V2 = c("0 John","1 wc44@email.com",  "wc44@email.com"),
                 V3 = c("1","0","A01Y Martin 3311290"))

dt

#                   V1               V2                  V3
# 1 Christian 21223456           0 John                   1
# 2                  x 1 wc44@email.com                   0
# 3     wc44@email.com   wc44@email.com A01Y Martin 3311290


# combine row elements in one big string
dt_rows = apply(dt, 1, function(x) paste(x,collapse = " "))

# update to lower case
IDs = tolower(IDs)
dt_rows = tolower(dt_rows)

# find in which row you have matches
sapply(IDs, grepl, dt_rows) 

#       a01y  ac43  bbn5  jk45  nt66  wc44
# [1,] FALSE FALSE FALSE FALSE FALSE FALSE
# [2,] FALSE FALSE FALSE FALSE FALSE  TRUE
# [3,]  TRUE FALSE FALSE FALSE FALSE  TRUE


# find which row id has a match (at least one match)
which(apply(sapply(IDs, grepl, dt_rows), 1, sum) >= 1) 

# [1] 2 3