Ecco un appello per un modo migliore di fare qualcosa che posso già fare in modo inefficiente: filtrare una serie di token n-grammi usando "stop words" in modo che il verificarsi di qualsiasi termine della parola di arresto in una rimozione di trigger n-grammo.Come rimuovere efficientemente le parole chiave da un elenco di token ngram in R
Mi piacerebbe molto avere una soluzione che funzioni sia per unigram sia per n-gram, anche se sarebbe ok avere due versioni, una con un flag "fixed" e una con un flag "regex". Sto mettendo insieme i due aspetti della domanda, dal momento che qualcuno potrebbe avere una soluzione che prova un approccio diverso che affronta sia i modelli di stopword di espressioni fisse che regolari.
Formati:
token sono un elenco di vettori di caratteri, che possono essere unigrams, o n-grammi concatenati da un carattere
_
(sottolineatura).stopwords sono un vettore di caratteri. In questo momento sono contento di lasciare che questo sia una stringa fissa, ma sarebbe un bel vantaggio essere in grado di implementare questo usando anche le stopword formattate con espressioni regolari.
uscita desiderata: Un elenco di caratteri corrispondenti dell'ingresso token ma con un token qualsiasi componente corrispondenza a una parola di arresto sia rimosso. (Questo significa una corrispondenza unigram, o una corrispondenza uno dei termini che l'n-gramma comprende.)
esempi, dati di test, e codice di lavoro e benchmark per costruire il:
tokens1 <- list(text1 = c("this", "is", "a", "test", "text", "with", "a", "few", "words"),
text2 = c("some", "more", "words", "in", "this", "test", "text"))
tokens2 <- list(text1 = c("this_is", "is_a", "a_test", "test_text", "text_with", "with_a", "a_few", "few_words"),
text2 = c("some_more", "more_words", "words_in", "in_this", "this_text", "text_text"))
tokens3 <- list(text1 = c("this_is_a", "is_a_test", "a_test_text", "test_text_with", "text_with_a", "with_a_few", "a_few_words"),
text2 = c("some_more_words", "more_words_in", "words_in_this", "in_this_text", "this_text_text"))
stopwords <- c("is", "a", "in", "this")
# remove any single token that matches a stopword
removeTokensOP1 <- function(w, stopwords) {
lapply(w, function(x) x[-which(x %in% stopwords)])
}
# remove any word pair where a single word contains a stopword
removeTokensOP2 <- function(w, stopwords) {
matchPattern <- paste0("(^|_)", paste(stopwords, collapse = "(_|$)|(^|_)"), "(_|$)")
lapply(w, function(x) x[-grep(matchPattern, x)])
}
removeTokensOP1(tokens1, stopwords)
## $text1
## [1] "test" "text" "with" "few" "words"
##
## $text2
## [1] "some" "more" "words" "test" "text"
removeTokensOP2(tokens1, stopwords)
## $text1
## [1] "test" "text" "with" "few" "words"
##
## $text2
## [1] "some" "more" "words" "test" "text"
removeTokensOP2(tokens2, stopwords)
## $text1
## [1] "test_text" "text_with" "few_words"
##
## $text2
## [1] "some_more" "more_words" "text_text"
removeTokensOP2(tokens3, stopwords)
## $text1
## [1] "test_text_with"
##
## $text2
## [1] "some_more_words"
# performance benchmarks for answers to build on
require(microbenchmark)
microbenchmark(OP1_1 = removeTokensOP1(tokens1, stopwords),
OP2_1 = removeTokensOP2(tokens1, stopwords),
OP2_2 = removeTokensOP2(tokens2, stopwords),
OP2_3 = removeTokensOP2(tokens3, stopwords),
unit = "relative")
## Unit: relative
## expr min lq mean median uq max neval
## OP1_1 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 100
## OP2_1 5.119066 3.812845 3.438076 3.714492 3.547187 2.838351 100
## OP2_2 5.230429 3.903135 3.509935 3.790143 3.631305 2.510629 100
## OP2_3 5.204924 3.884746 3.578178 3.753979 3.553729 8.240244 100
il metodo di eliminazione stopword in tm o qdap non è sufficiente? Anche se funzionano in un altro modo, prima rimuovi le stopword e poi crea i n-grammi. – phiver
No, è abbastanza facile, sto cercando di capire un modo efficace per rimuovere gli ngram contenenti stopword dopo la costruzione. –
Hai controllato il nuovo pacchetto di Tyler Rinker, termco su github? Sembra promettente. Non ho ancora avuto il tempo di verificarlo. – phiver