Объединение двухчленной матрицы в 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