2015-11-27 36 views
2

我有一個很大的數據框,我正在識別字符串中的模式,然後提取它們。我提供了一小部分來說明我的任務。我通過創建具有多個單詞的TermDocumentMatrix來生成我的模式。我將這些模式與來自stringi和stringr軟件包的stri_extract和str_replace一起在'punct_prob'數據框中搜索。R我如何使用TermDocumentMatrix保留標點符號()

我的問題是,我需要在'punct_prob $ description'內保持標點符號以保持每個字符串中的字面含義。例如,我不能有2.35毫米變成235毫米。然而,我正在使用的TermDocumentMatrix過程是去除標點符號(或者至少是句點),因此我的模式搜索功能無法匹配它們。

總之......如何在生成TDM時保持標點符號?我試過在TermDocumentMatrix控制參數中包含removePunctuation = FALSE,但沒有成功。

library(tm) 
punct_prob = data.frame(description = tolower(c("CONTRA ANGLE HEAD 2:1 FOR 2.35mm BUR", 
            "TITANIUM LINE MINI P.B F.O. TRIP SPRAY", 
            "TITANIUM LINE POWER P. B F.O. TRIP SPR", 
            "MEDESY SPECIAL ITEM"))) 

punct_prob$description = as.character(punct_prob$description) 

# a control for the number of words in phrases 
max_ngram = max(sapply(strsplit(punct_prob$description, " "), length)) 

#set up ngrams and tdm 
BigramTokenizer <- function(x) {RWeka::NGramTokenizer(x, RWeka::Weka_control(min = max_ngram, max = max_ngram))} 
punct_prob_corpus = Corpus(VectorSource(punct_prob$description)) 
punct_prob_tdm <- TermDocumentMatrix(punct_prob_corpus, control = list(tokenize = BigramTokenizer, removePunctuation=FALSE)) 
inspect(punct_prob_tdm) 

檢查結果 - 不帶標點符號....

        Docs 
Terms        1 2 3 4 
    angle head 2 1 for 2 35mm bur 1 0 0 0 
    contra angle head 2 1 for 2 35mm 1 0 0 0 
    line mini p b f o trip spray  0 1 0 0 
    line power p b f o trip spr  0 0 1 0 
    titanium line mini p b f o trip 0 1 0 0 
    titanium line power p b f o trip 0 0 1 0 

感謝提前任何幫助:)

回答

3

的問題是沒有這麼多的termdocumentmatrix,但NGRAM分詞基礎在RWEKA。 Rweka在標記化時刪除標點符號。

如果您使用nlp標記器它會保留標點符號。見下面的代碼。

P.S.我在第三行中刪除了一個空格,所以P.B.是P.B.像它是第2行

library(tm) 
punct_prob = data.frame(description = tolower(c("CONTRA ANGLE HEAD 2:1 FOR 2.35mm BUR", 
               "TITANIUM LINE MINI P.B F.O. TRIP SPRAY", 
               "TITANIUM LINE POWER P.B F.O. TRIP SPR", 
               "MEDESY SPECIAL ITEM"))) 
punct_prob$description = as.character(punct_prob$description) 

max_ngram = max(sapply(strsplit(punct_prob$description, " "), length)) 

punct_prob_corpus = Corpus(VectorSource(punct_prob$description)) 




NLPBigramTokenizer <- function(x) { 
    unlist(lapply(ngrams(words(x), max_ngram), paste, collapse = " "), use.names = FALSE) 
} 


punct_prob_tdm <- TermDocumentMatrix(punct_prob_corpus, control = list(tokenize = NLPBigramTokenizer)) 
inspect(punct_prob_tdm) 

<<TermDocumentMatrix (terms: 3, documents: 4)>> 
Non-/sparse entries: 3/9 
Sparsity   : 75% 
Maximal term length: 38 
Weighting   : term frequency (tf) 

             Docs 
Terms         1 2 3 4 
    contra angle head 2:1 for 2.35mm bur 1 0 0 0 
    titanium line mini p.b f.o. trip spray 0 1 0 0 
    titanium line power p.b f.o. trip spr 0 0 1 0 
+0

謝謝@phiver - 非常感謝! – CallumH

1

quanteda包是足夠聰明而不處理字內的標點字符爲「標點符號」到tokenise。這讓人很容易的構建你的矩陣:

txt <- c("CONTRA ANGLE HEAD 2:1 FOR 2.35mm BUR", 
     "TITANIUM LINE MINI P.B F.O. TRIP SPRAY", 
     "TITANIUM LINE POWER P.B F.O. TRIP SPR", 
     "MEDESY SPECIAL ITEM") 

require(quanteda) 
myDfm <- dfm(txt, ngrams = 6:8, concatenator = " ") 
t(myDfm) 
#          docs 
# features        text1 text2 text3 text4 
# contra angle head for 2.35mm bur   1  0  0  0 
# titanium line mini p.b f.o trip   0  1  0  0 
# line mini p.b f.o trip spray    0  1  0  0 
# titanium line mini p.b f.o trip spray  0  1  0  0 
# titanium line power p.b f.o trip   0  0  1  0 
# line power p.b f.o trip spr    0  0  1  0 
# titanium line power p.b f.o trip spr  0  0  1  0 

如果您想保留「標點符號」,它將被標記化作爲一個單獨的令牌當它結束的一個術語:

myDfm2 <- dfm(txt, ngrams = 8, concatenator = " ", removePunct = FALSE) 
t(myDfm2) 
#           docs 
# features         text1 text2 text3 text4 
# titanium line mini p.b f.o . trip spray  0  1  0  0 
# titanium line power p.b f.o . trip spr  0  0  1  0 

注意這裏說的ngrams參數是完全靈活的,並且可以採用ngram大小的向量,如第一個示例中ngrams = 6:8指示它應該形成6,7和8克。

+0

謝謝@Ken。我很快就會玩這個遊戲。我喜歡可變的ngram長度這個想法,這是我首先進入RWeka記號器的原因之一。 – CallumH

相關問題