2017-02-23 21 views
3

我知道「splitstackshape」中的「cSplit_e」可以用來轉換一列下的多個值,以便用二進制值分隔列。我正在處理用於計算tf-idf的文本問題,並且在列的下方顯示所有唯一值並不是必須的。例如,修改cSplit_e函數以解釋多個值

docname ftype      doc_text 
    1  mw    hello, hi, how, are, you, hello 
    2  gw      hi,yo,man 
    3  mw      woha,yo, yoman 

DPUT(DF)

structure(list(docname = 1:3, ftype = c("mw", "gw", "mw"), doc_text = structure(1:3, .Label = c("hello, hi, how, are, you, hello", 
"hi,yo,man", "woha,yo, yoman"), class = "factor")), .Names = c("docname", 
"ftype", "doc_text"), class = "data.frame", row.names = c(NA, 
-3L)) 

對於上面的例子,如果我們考慮該文檔-1,然後cSplit_e將doc_text具有值轉換成5個單獨的列的 「1」 時「你好「出現兩次。有沒有辦法修改這個函數來解釋重複的值?

從本質上說,這裏就是我想實現:如果有一個數據幀

DOCNAME FTYPE doc_text 1兆瓦你好,你好,怎麼樣,是你,你好 2 GW嗨,喲,人 3 me woha,yo,yoman

我想根據由「,」分隔的列值將doc_text轉換爲多列,並獲取它們各自的頻率。所以結果應該是

docname ftype are hello hi how man woha yo yoman you 
    1 mw 1  2 1 1 0 0 0  0 1 
    2 gw 0  0 1 0 1 0 1  0 0 
    3 mw 0  0 0 0 0 1 1  1 0 

如果有人知道如何做到這一點使用「splitstackshape」或通過不同的方式,我會升值。最終的目標是計算tf-idf。

謝謝。

回答

3

我們可以通過 'doc_text'

library(qdapTools) 
cbind(df[1], mtabulate(strsplit(as.character(df$doc_text), ",\\s*"))) 
# docname are hello hi how man woha yo yoman you 
#1  1 1  2 1 1 0 0 0  0 1 
#2  2 0  0 1 0 1 0 1  0 0 
#3  3 0  0 0 0 0 1 1  1 0 

或者另一種選擇拆分後mtabulate做,這是tidyverse

library(tidyverse) 
separate_rows(df, doc_text) %>% #split to long format 
      group_by(docname, doc_text) %>% #group by variables 
      tally() %>% #get the frequency 
      spread(doc_text, n, fill=0) #reshape to wide 

或者作爲@Frank建議

library(splitstackshape) 
cSplit(df, "doc_text", ",", "long")[, dcast(.SD, docname ~ doc_text)] 
+2

感謝@akrun和弗蘭克。 – syebill

2

隨着一點點的text-mining

docs <- gsub('[[:punct:]]+', ' ', as.character(df$doc_text)) 
library(tm) 
corpus <- Corpus(VectorSource(docs)) 

# compute Term Frequencies 
as.matrix(DocumentTermMatrix(corpus, control = list(wordLengths=c(2,Inf)))) 
#  Terms 
#Docs are hello hi how man woha yo yoman you 
# 1 1  2 1 1 0 0 0  0 1 
# 2 0  0 1 0 1 0 1  0 0 
# 3 0  0 0 0 0 1 1  1 0 

# compute Tf-Idf scores 
as.matrix(DocumentTermMatrix(corpus, control = list(wordLengths=c(2,Inf), weighting=weightTfIdf))) 
#   Terms 
#Docs  are  hello   hi  how  man  woha  yo  yoman`  you 
# 1 0.2641604 0.5283208 0.09749375 0.2641604 0.0000000 0.0000000 0.0000000 0.0000000 0.2641604 
# 2 0.0000000 0.0000000 0.19498750 0.0000000 0.5283208 0.0000000 0.1949875 0.0000000 0.0000000 
# 3 0.0000000 0.0000000 0.00000000 0.0000000 0.0000000 0.5283208 0.1949875 0.5283208 0.0000000 
+0

根據您的第一行來判斷,這會將多字值(如「hello world」)視爲單獨的值。如果是這樣,你可能想提一下這個警告。 – Frank

+2

@Frank是它是'bag of words'的表示形式,所以不會考慮'n> 1'的n-gram,例如短語。 –

+0

@Sandipan。我可以看到你已經刪除了標點符號來刪除「,」但是如果文本中有意義的標點符號應該構成單詞的一部分呢?我應該省略第一步並遵循其他步驟?你也可以闡明「wordLengths = c(2,Inf)」。它是否用於指定文檔中的最小和最大字長? – syebill