Как извлечь текст с помощью разделителей, если некоторые разделители отсутствуют - PullRequest
0 голосов
/ 18 декабря 2018

Я пытаюсь извлечь текст в соответствии с заголовками в полуструктурированном текстовом документе.

Ввод

Column<-"Order:1223442 Subject:History Name Bilbo Johnson Grade: Bad Report: Need to complete Conclusion: Dud"

Вывод здесь

Order     Subject Name           Grade  Report           Conclusion
1223442   History Bilbo Johnson   Bad   Need to complete  Dud

Я могу добиться этого с помощью следующей (грязной, но работающей) функции:

dataframeIn<-data.frame(Column,stringsAsFactors=FALSE)
delim<-c("Order","Subject","Name","Grade","Report","Conclusion")


Extractor <- function(dataframeIn, Column, delim) {
  dataframeInForLater<-dataframeIn
  ColumnForLater<-Column
  Column <- rlang::sym(Column)
  dataframeIn <- data.frame(dataframeIn)
  dataframeIn<-dataframeIn %>%
    tidyr::separate(!!Column, into = c("added_name",delim),
                                          sep = paste(delim, collapse = "|"),
                    extra = "drop", fill = "right")
  names(dataframeIn) <- gsub(".", "", names(dataframeIn), fixed = TRUE)

  dataframeIn<-data.frame(dataframeIn)
  #Add the original column back in so have the original reference
  dataframeIn<-cbind(dataframeInForLater[,ColumnForLater],dataframeIn)
  dataframeIn<-data.frame(dataframeIn)
  return(dataframeIn)
}

Extractor(dataframeIn, "Column", delim)

Однако иногда отсутствуют разделители, например

Order:1223442 Subject:History Name Bilbo Johnson Grade: Bad Conclusion: Dud

В этом случае желаемым выходным значением является

Order     Subject Name           Grade  Conclusion
1223442   History Bilbo Johnson   Bad    Dud

, но фактическим выходным значением становится:

 Order   Subject            Name   Grade Report Conclusion
:1223442  :History   Bilbo Johnson  : Bad    : Dud       <NA>

Как можно учесть отсутствующие разделители, хотя они находятся в том же порядке (включаяразделители, которые отсутствуют в середине текста, а также в конце, как в примере выше)?

1 Ответ

0 голосов
/ 18 декабря 2018

Мы можем сделать следующее (это только извлечение текста, я оставляю конструирование вывода для вас):

library(stringr)
Extractor <- function(x, delim) {
  pattern <- paste0(delim, ":{0,1}(.*?)(", paste(c(delim, "$"), collapse = "|"), ")")
  trimws(str_match(x, pattern)[, 2])
}
Extractor(Column1, delim)
# [1] "1223442"          "History"          "Bilbo Johnson"    "Bad"              "Need to complete" "Dud"
Extractor(Column2, delim)
# [1] "1223442"       "History"       "Bilbo Johnson" "Bad"           NA              "Dud"
Column3 <- "Subject:History Name Bilbo Johnson"
Extractor(Column3, delim)
# [1] NA              "History"       "Bilbo Johnson" NA              NA              NA

Так как у нас есть NA, ясно, что разделители отсутствовали и что не былот.

В вашем случае это работает так, что у нас есть серия шаблонов

pattern
# [1] "Order:{0,1}(.*?)(Order|Subject|Name|Grade|Report|Conclusion|$)"     
# [2] "Subject:{0,1}(.*?)(Order|Subject|Name|Grade|Report|Conclusion|$)"   
# [3] "Name:{0,1}(.*?)(Order|Subject|Name|Grade|Report|Conclusion|$)"      
# [4] "Grade:{0,1}(.*?)(Order|Subject|Name|Grade|Report|Conclusion|$)"     
# [5] "Report:{0,1}(.*?)(Order|Subject|Name|Grade|Report|Conclusion|$)"    
# [6] "Conclusion:{0,1}(.*?)(Order|Subject|Name|Grade|Report|Conclusion|$)"

Затем str_match nice извлекает часть (.*?) во вторые выходные столбцы, и мыизбавьтесь от любых пробелов с помощью trimws.И мы используем ленивое соответствие в (.*?), чтобы не слишком сильно совпадать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...