2017-01-24 6 views
1

Пусть текстовые данные выглядят следующим образом:R: Extract контролируемого словаря из вектора символов

txt <- c("peter likes red", "mary likes green", "bob likes blue") 

Я хочу, чтобы уменьшить эти строки на слова из этого контролируемого словаря:

voc <- c("peter", "mary", "bob", "red", "green", "blue") 

Результат должен быть вектор:

c("peter red", "mary green", "bob blue") 

можно использовать tm библиотеку, но это дает только me плотная матрица документов:

foo <- VCorpus(VectorSource(txt)) 
inspect(DocumentTermMatrix(foo, list(dictionary = voc))) 
Non-/sparse entries: 6/12 
Sparsity   : 67% 
Maximal term length: 5 
Weighting   : term frequency (tf) 

    Terms 
Docs blue bob green mary peter red 
    1 0 0  0 0  1 1 
    2 0 0  1 1  0 0 
    3 1 1  0 0  0 0 

Как получить векторное решение с одной строкой на векторный элемент?

Решение должно быть быстрым. Я также большой поклонник базы R.

EDIT: Сравнение решений до сих пор

По моим данным, Джеймс решение примерно в четыре раза быстрее, чем SOTOS. Но у меня заканчивается память, когда я делаю шаг от length(text) от 1k до 10k. Решение Sotos все еще работает на 10k.

Учитывая, что у моих данных есть length(txt) ~ 1M и length(voc) ~ 5k Я полагаю, что для решения Sotos потребуется 18 часов, учитывая, что у него не хватает памяти.

Не может быть быстрее?

+0

Достаточно ли для вашего случая недостаточно регулярного выражения? Например. что-то вроде 'sapply (strsplit (txt," ", TRUE), function (x) paste (collapse =" ", x [x% in% voc]))' –

+0

@alexis_laz вы выигрываете! Ваше решение заканчивается через 10 минут вместо 18 часов. Вы хотите создать выделенный ответ, чтобы я мог отметить его как решение? – hyco

ответ

2

Вы можете использовать stringi

library(stringi) 
sapply(stri_extract_all_regex(txt, paste0('\\b', voc, collapse = '|', '\\b')), paste, collapse = ' ') 
#[1] "peter red" "mary green" "bob blue" 

или полный stringi

stri_paste_list(stri_extract_all_regex(txt, paste0('\\b', voc, collapse = '|', '\\b')), sep = ' ') 
#[1] "peter red" "mary green" "bob blue" 
+0

Я проверяю ваши решения. Обратите внимание, что результат 'txt <- c (« peters like reds »,« marys like greens »,« bobs like blues »)' должен быть пустым. – hyco

+0

Что значит «должно быть пусто»? – Sotos

+0

Я имею в виду, что ваше первое решение не должно извлекать 'peter' из' peters'. Другими словами, 'peters' не находится в контролируемом vocabulyry,' peter' is. – hyco

3

бейс только метод:

apply(sapply(paste0("\\b",voc,"\\b"), function(x) grepl(x,txt)), 1, function(x) paste(voc[x],collapse=" ")) 
[1] "peter red" "mary green" "bob blue" 

sapply часть воссоздает матрицу членства вы использовали пакет тм для, в то время как apply выполняет итерации по своим строкам, чтобы вытащить соответствующие термины из словаря, чтобы вставить их вместе.

+0

@Sotos Я исправил его, чтобы добавить границы слов, поэтому он должен работать сейчас. – James