2016-10-05 6 views
1

У меня есть большая таблица данных, где я хочу проверить, присутствует ли 103a_foo. Однако имена файлов в большой таблице они написаны по-разному, поэтому я должен использовать регулярное выражение.Найти первое совпадение подстроки в столбце больших данных.table

dt = structure(list(myID = c("86577", "34005","34005", 
"194000", "30252", "71067"), 
filename = c("/scratch/tmpdir/12a_foo.mzXML.gz", 
"/scratch/tmpdir/103b_foo.XML.gz", "/scratch/tmpdir/103a_foo.XML.gz", 
"/scratch/tmpdir/103a_foo.XML.gz", 
"/scratch/tmpdir/100b_foo.XML.gz", "/scratch/tmpdir/108a_foo.XML.gz")), 
class = c("data.table", "data.frame"), 
row.names = c(NA, -5L), 
.Names = c("myID", "filename")) 

В качестве выхода я хочу индекс 3, так как это первый раз. Я бы использовал grep('103a_foo', dt$filename)[1], но я хочу, чтобы поиск останавливался при первом вступлении, так как таблица большая (10 миллионов строк).

ответ

6

Если вы установили fixed = TRUE, это не займет так много времени. Это слишком медленно для ваших нужд?

x <- sample(dt$filename, 1e7, TRUE) 
library(microbenchmark) 
microbenchmark(grep('103a_foo', x), 
       grep('103a_foo',dt$filename, fixed = TRUE), 
       times = 5) 

#Unit: milliseconds 
#        expr  min  lq  mean #median  uq  max neval cld 
#    grep("103a_foo", x) 2124.8178 2125.707 2128.7849 2127.542 2128.2054 2137.6532  5 b 
# grep("103a_foo", x, fixed = TRUE) 826.2298 826.597 832.7058 829.969 840.1974 840.5359  5 

Насколько мне известно, не существует эффективный способ реализации grep, нарушающие из цикла векторизации с использованием чистого R. Вы можете использовать Rcpp, если вам это нужно часто.

+0

Я сомневаюсь, что 103a_foo является реальным регулярным выражением. –

+1

@ WiktorStribiżew OP не дает никаких указаний на то, что она действительно нуждается в регулярном выражении. На основе ее профиля она могла бы искать определенную последовательность букв TACG. – Roland

+0

См. Http://gallery.rcpp.org/articles/boost-regular-expressions/, если вы хотите использовать Rcpp для этого. – Roland

2

Как отметил @Roland, с grep вы не сможете остановиться в первом матче. Однако, если вам нужно часто выполнять описанные вами операции, может оказаться полезным извлечь раз и навсегда «базовые имена», которые вы собираетесь просмотреть, а затем использовать match (который фактически ломается при первом вхождении). Что-то вроде:

#this line might not work depending on the actual format of your real data 
basenames<-gsub("^.*/|\\..*$","",dt$filename) 
#then we use match 
match("103a_foo",basenames) 
#[1] 3