Как извлечь текст с помощью разделителей, когда некоторые разделители отсутствуют

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

Вход

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>

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

После Name нет двоеточия. Всегда ли это возможность или опечатка?

Julius Vainora 18.12.2018 14:14

@JuliusVainora да, двоеточие иногда отсутствует, поэтому, к сожалению, нельзя полагаться на него для разделения

Sebastian Zeki 18.12.2018 14:16
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
2
37
1

Ответы 1

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

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. Ах, и мы используем ленивое сопоставление в (.*?), чтобы не совпадать слишком много.

Другие вопросы по теме