R: найти ngram, используя dfm, когда в одном документе несколько предложений

У меня большой набор данных (>1 миллиона строк), и каждая строка представляет собой текст из нескольких предложений. Например, следующий пример из 2 строк:

mydat <- data.frame(text=c('I like apple. Me too','One two. Thank you'),stringsAsFactors = F)

То, что я пытался сделать, это извлечь термины биграммы в каждой строке ("." Сможет разделять термины ngram). Если я просто использую функцию dfm:

mydfm  = dfm(mydat$text,toLower = T,removePunct = F,ngrams=2)
dtm = as.DocumentTermMatrix(mydfm)
txt_data = as.data.frame(as.matrix(dtm))

Вот условия, которые я получил:

"i_like"     "like_apple" "apple_."    "._me"       "me_too"     "one_two"    "two_."      "._thank"    "thank_you" 

Это то, что я ожидаю, в основном "." пропускается и используется для разделения терминов:

"i_like"     "like_apple"  "me_too"     "one_two"    "thank_you" 

Поверьте, написание медленных циклов также может решить эту проблему, но, учитывая, что это огромный набор данных, я бы предпочел эффективные способы, аналогичные dfm() в quanteda, для решения этой проблемы. Мы ценим любые предложения!

2 ответа

Решение

Если ваша цель просто извлечь эти биграммы, то вы можете использовать tokens дважды. Один раз токенизировать до предложений, затем снова составить нграммы для каждого предложения.

library("quanteda")
mydat$text %>% 
    tokens(mydat$text, what = "sentence") %>% 
    as.character() %>%
    tokens(ngrams = 2, remove_punct = TRUE) %>%
    as.character()
#[1] "I_like"     "like_apple" "Me_too"     "One_two"    "Thank_you"

Вставьте tokens_tolower() после первого tokens() позвоните, если хотите, или используйте char_tolower() в конце.

Ответ @Jota работает, но есть способ более точно контролировать токенизацию, вызывая ее только один раз:

(toks <- tokenize(toLower(mydat$text), removePunct = 2, ngrams = 2))
## tokenizedText object from 2 documents.
## Component 1 :
## [1] "i_like"     "like_apple" "apple_me"   "me_too"    
## 
## Component 2 :
## [1] "one_two"   "two_thank" "thank_you"

dfm(toks)
## Document-feature matrix of: 2 documents, 7 features.
## 2 x 7 sparse Matrix of class "dfmSparse"
##        features
## docs    i_like like_apple apple_me me_too one_two two_thank thank_you
##   text1      1          1        1      1       0         0         0
##   text2      0          0        0      0       1         1         1

Добавлено:

Затем удалить любой Ngram с . Вы можете использовать пунктуацию: следующее, по умолчанию valuetype = "glob":

removeFeatures(toks2, "*.*")
## tokenizedText object from 2 documents.
## Component 1 :
## [1] "i_like"     "like_apple" "me_too"    
## 
## Component 2 :
## [1] "one_two"   "thank_you"
Другие вопросы по тегам