Объединение двухчленной матрицы в R

У меня есть две матрицы термина документа. Я не могу принять объединение этих двух матриц в качестве матрицы двух разных длин.

A <- data.frame(name = c(
  "X-ray right leg arteries",
  "x-ray left shoulder",
  "x-ray leg arteries",
  "x-ray leg with 20km distance"
), stringsAsFactors = F)

B <- data.frame(name = c(
  "X-ray left leg arteries",
  "X-ray leg",
  "xray right leg",
  "X-ray right leg arteries"
), stringsAsFactors = F)


library(tm)

# A
doc_corpus <- Corpus(VectorSource(A$name))
control_list <- list(weighting=weightBin, removePunctuation = TRUE, stopwords = TRUE, tolower = TRUE)
dtm <- DocumentTermMatrix(doc_corpus, control = control_list)
tf <- as.matrix(dtm)

# B
doc_corpus2 <- Corpus(VectorSource(B$name))
control_list2 <- list(weighting=weightBin, removePunctuation = TRUE, stopwords = TRUE, tolower = TRUE)
dtm2 <- DocumentTermMatrix(doc_corpus2, control = control_list)
tf2 <- as.matrix(dtm2)

тс [1,]

arteries      leg      ray    right     left shoulder     20km distance 
       1        1        1        1        0        0        0        0

TF2[4,]

arteries     left      leg      ray    right     xray 
       1        0        1        1        1        0 

Если я возьму сумму умножения этих двух матриц, он вернет 3. Это должно быть 4. Чтобы исправить это,

sum(tf[1,][tf[1,]==1] * tf2[4,][tf2[4,]==1])

Но это не учитывает сроки при расчете. Например, сравнить tf[1,] а также tf2[1,]

sum(tf[1,][tf[1,]==1] * tf2[1,][tf2[1,]==1])

Должно быть 3, но возвращается к 4.

Я выполняю приведенный выше расчет, чтобы рассчитать косинусное сходство (см. Формулу ниже).

similarity = (sum(tf[1,] * tf2[4,])) / ( sqrt(sum(tf2[4,] ^ 2)) * sqrt(    sum(tf[1,] ^ 2)))

2 ответа

Вот способ, который не только более прост, но и поддерживает полную разреженность объектов. Чтобы вычислить косинусное сходство, используя подход, о котором идет речь в этом вопросе, вы превращаете потенциально очень большую матрицу термина документа в плотную матрицу. Метод ниже избегает этого.

library("quanteda")

corp1 <- corpus(A, text_field = "name")
corp2 <- corpus(B, text_field = "name")

# unnecessary but better for distiguishing documents
docnames(corp1) <- paste("A", seq_len(ndoc(corp1)), sep = ".")
docnames(corp2) <- paste("B", seq_len(ndoc(corp2)), sep = ".")

The rbind.dfm() Метод волшебным образом присоединится к ним и будет соответствовать функциям. (Примечание: эквивалентный способ сделать это будет использовать + оператор для объединения корпусных объектов: dtm2 <- dfm(corp1 + corp2), Попытайся!)

dtm3 <- rbind(dfm(corp1), dfm(corp2))
dtm3
# Document-feature matrix of: 8 documents, 10 features (65% sparse).
# 8 x 10 sparse Matrix of class "dfm"
#      features
# docs  x-ray right leg arteries left shoulder with 20km distance xray
#   A.1     1     1   1        1    0        0    0    0        0    0
#   A.2     1     0   0        0    1        1    0    0        0    0
#   A.3     1     0   1        1    0        0    0    0        0    0
#   A.4     1     0   1        0    0        0    1    1        1    0
#   B.1     1     0   1        1    1        0    0    0        0    0
#   B.2     1     0   1        0    0        0    0    0        0    0
#   B.3     0     1   1        0    0        0    0    0        0    1
#   B.4     1     1   1        1    0        0    0    0        0    0

(Разреженное) вычисление матрицы подобия косинуса как dist Объект класса тогда:

textstat_simil(dtm3, method = "cosine")
#           A.1       A.2       A.3       A.4       B.1       B.2       B.3
# A.2 0.2886751                                                            
# A.3 0.8660254 0.3333333                                                  
# A.4 0.4472136 0.2581989 0.5163978                                        
# B.1 0.7500000 0.5773503 0.8660254 0.4472136                              
# B.2 0.7071068 0.4082483 0.8164966 0.6324555 0.7071068                    
# B.3 0.5773503 0.0000000 0.3333333 0.2581989 0.2886751 0.4082483          
# B.4 1.0000000 0.2886751 0.8660254 0.4472136 0.7500000 0.7071068 0.5773503

Не нужно использовать bind_rows()

Вы можете объединить два corpus или два dtm с c()

как в документации:

tm_combine: объединение нескольких корпусов в один, объединение нескольких документов в единое целое, объединение нескольких матриц терминологических документов в один или объединение многочастотных векторов частотных терминов в одну матрицу терминологических документов.

#S3 method for class 'VCorpus' 
c(..., recursive = FALSE)
##S3 method for class 'TextDocument' 
c(..., recursive = FALSE)
##S3 method for class 'TermDocumentMatrix' 
c(..., recursive = FALSE)
##S3 method for class 'term_frequency' 
c(..., recursive = FALSE)

Используя ваши DTM и DTM2:

dtm3 <- c(dtm, dtm2)
as.matrix(dtm3)

    Terms
Docs arteries leg ray right left shoulder 20km distance xray
   1        1   1   1     1    0        0    0        0    0
   2        0   0   1     0    1        1    0        0    0
   3        1   1   1     0    0        0    0        0    0
   4        0   1   1     0    0        0    1        1    0
   1        1   1   1     0    1        0    0        0    0
   2        0   1   1     0    0        0    0        0    0
   3        0   1   0     1    0        0    0        0    1
   4        1   1   1     1    0        0    0        0    0
Другие вопросы по тегам