Я пытаюсь извлечь текст в соответствии с заголовками в частично структурированном текстовом документе.
Вход
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>
Как я могу учесть отсутствие разделителей, хотя они находятся в том же порядке (включая разделители, которые отсутствуют в середине текста, а также в конце, как в примере выше)?
@JuliusVainora да, двоеточие иногда отсутствует, поэтому, к сожалению, нельзя полагаться на него для разделения
Мы можем сделать следующее (это только извлечение текста, я оставляю создание вывода для вас):
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
. Ах, и мы используем ленивое сопоставление в (.*?)
, чтобы не совпадать слишком много.
После
Name
нет двоеточия. Всегда ли это возможность или опечатка?