Простое сравнение двух текстов в R

#r

#r #сравнение

Вопрос:

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

на основе идей @joris Meys я добавил массив для разделения текста на предложения и придаточные предложения.

вот как это выглядит:

   textparts <- function (text){
  textparts <- c("\,", "\.")
  i <- 1
  while(i<=length(textparts)){
        text <- unlist(strsplit(text, textparts[i]))
        i <- i 1
  }
  return (text)
}

textparts1 <- textparts("This is a complete sentence, whereas this is a dependent clause. This thing works.")
textparts2 <- textparts("This could be a sentence, whereas this is a dependent clause. Plagiarism is not cool. This thing works.")

  commonWords <- intersect(textparts1, textparts2)
  commonWords <- paste("\<(",commonWords,")\>",sep="")


  for(x in commonWords){
    textparts1 <- gsub(x, "\1*", textparts1,ignore.case=TRUE)
    textparts2 <- gsub(x, "\1*", textparts2,ignore.case=TRUE)
  }
  return(list(textparts1,textparts2))
  

Однако иногда это работает, иногда нет.

Я хотел бы получить такие результаты:

 >   return(list(textparts1,textparts2))
[[1]]
[1] "This is a complete sentence"         " whereas this is a dependent clause*" " This thing works*"                  

[[2]]
[1] "This could be a sentence"            " whereas this is a dependent clause*" " Plagiarism is not cool"             " This thing works*"           
  

в то время как я не получаю никаких результатов.

Комментарии:

1. Взгляните на CRAN taskview для обработки естественного языка для вдохновения: cran.r-project.org/web/views/NaturalLanguageProcessing.html

2. спасибо, я знаю об этом сайте. Есть детектор предложений, который мог бы быть полезен для меня, но нет ни одного сравнения предложений, выделяющего то, что я ищу

3. хехе, теперь вы вводите людей в заблуждение. Вы можете добавлять комментарии, если решение не то, что вы ищете, но вам не следует изменять содержание вашего вопроса. Это совершенно другой вопрос. Во-вторых, вы не кодируете C, вы кодируете R. Эта конструкция while() отвратительна. сделайте for(i in textparts) и удалите все остальное. И затем вы должны взглянуть на то, что происходит. У вас могут быть пробелы здесь и там, что испортит ваш результат. У вас могут быть различия в верхнем и нижнем регистре. Просмотрите файлы справки и проверьте свои промежуточные результаты, и вы решите проблему.

Ответ №1:

Есть некоторые проблемы с ответом @Chase :

  • различия в прописных буквах не учитываются
  • вмешательство может испортить результаты
  • если есть более одного похожего слова, то вы получаете много предупреждений из-за вызова gsub.

Основываясь на его идее, существует следующее решение, которое использует tolower() и некоторые приятные функциональные возможности регулярных выражений :

 compareSentences <- function(sentence1, sentence2) {
  # split everything on "not a word" and put all to lowercase
  x1 <- tolower(unlist(strsplit(sentence1, "\W")))
  x2 <- tolower(unlist(strsplit(sentence2, "\W")))

  commonWords <- intersect(x1, x2)
  #add word beginning and ending and put words between ()
  # to allow for match referencing in gsub
  commonWords <- paste("\<(",commonWords,")\>",sep="")


  for(x in commonWords){ 
    # replace the match by the match with star added
    sentence1 <- gsub(x, "\1*", sentence1,ignore.case=TRUE)
    sentence2 <- gsub(x, "\1*", sentence2,ignore.case=TRUE)
  }
  return(list(sentence1,sentence2))      
}
  

Это дает следующий результат :

 text1 <- "This is a test. Weather is fine"
text2 <- "This text is a test. This weather is fine. This blabalba This "

compareSentences(text1,text2)
[[1]]
[1] "This* is* a* test*. Weather* is* fine*"

[[2]]
[1] "This* text is* a* test*. This* weather* is* fine*. This* blabalba This* "
  

Комментарии:

1. большое спасибо. еще 1 вопрос: это очень полезно для одного или двух предложений. я хотел бы проанализировать тексты из 10-15 предложений. Другими словами, было бы лучше выполнить поиск по триграммам.

2. @digitalaxp: у вас есть все строительные блоки. Смотрите ?regex и ?strsplit , например. Это не сложно, но и бесплатно нанять программиста не получится.

3. @joris-meys извините, это моя вина! в любом случае, я попробовал это самостоятельно и отредактировал свой первый пост.

Ответ №2:

Я уверен, что на странице обработки естественного языка есть гораздо более надежные функции, но вот одно решение, использующее intersect() для поиска общих слов. Подход заключается в том, чтобы прочитать два предложения, определить общие слова и gsub() их комбинацию из слова и прозвища по нашему выбору. Здесь я решил использовать * , но вы могли бы легко изменить это или добавить что-то еще.

 sent1 <- "I shot the sheriff."
sent2 <- "Dick Cheney shot a man."

compareSentences <- function(sentence1, sentence2) {
  sentence1 <- unlist(strsplit(sentence1, " "))
  sentence2 <- unlist(strsplit(sentence2, " "))

  commonWords <- intersect(sentence1, sentence2)

  return(list(
      sentence1 = paste(gsub(commonWords, paste(commonWords, "*", sep = ""), sentence1), collapse = " ")
    , sentence2 = paste(gsub(commonWords, paste(commonWords, "*", sep = ""), sentence2), collapse = " ")
    ))
}

> compareSentences(sent1, sent2)
$sentence1
[1] "I shot* the sheriff."

$sentence2
[1] "Dick Cheney shot* a man."
  

Комментарии:

1. Ну, человек, которого застрелил Чейни, технически был адвокатом.

2. 1 для пересечения. Я взял вашу идею и немного доработал ее для получения более общего решения.