Решения Regex невероятно чувствительны к формированию предложений, и, поскольку они имеют нерегулярный интервал, я предполагаю , что они либо созданы человеком, либо созданы с помощью нерегулярного / противоречивого процесса. Отклонения от этого шаблона, безусловно, приведут к разрыву частей.
Таким образом, я делаю это настолько конкретным и надежным, насколько это возможно, чтобы (1) столбцы сохранялись, даже если не были найдены, и (2) искаженные предложенияне скучайте по работам.
Я предполагаю, что вы прочитали бы в ваших данных что-то вроде:
dat <- readLines("path/to/file.txt")
, поэтому для демонстрационных данных я буду использовать
dat <- strsplit("-The$data 1 is taken on Aug, 2009 at UBC
and is significant with p value <0.01
-The$data 2 is taken on Sep, 2012 at SFU
and is not significant with p value > 0.06
-This$datum is different from the others
and is not significant", "[\n\r]")[[1]]
Здесь я буду использовать трюк cumsum(grepl(...))
, чтобы найти случаи, когда я знаю, что начинается строка, а затем сгруппировать следующие строки.
cumsum(grepl("^-", dat))
# [1] 1 1 1 2 2 2 3 3
combined <- unlist(as.list(by(dat, cumsum(grepl("^-", dat)), paste, collapse = "\n")), use.names=FALSE)
combined
# [1] "-The$data 1 is taken on Aug, 2009 at UBC\nand is significant with p value <0.01\n"
# [2] "-The$data 2 is taken on Sep, 2012 at SFU\nand is not significant with p value > 0.06\n"
# [3] "-This$datum is different from the others\nand is not significant"
Теперь, когда строкисгруппированы по логике, вот подробный, но (я считаю) в основном надежный метод для разбора нужных вам столбцов. (Должен отметить, что, безусловно, выполнимо написать одно регулярное выражение, которое пытается захватить все; проблема в том, хотите ли вы захватить большинство вещей, если они есть, или просто потерпеть неудачу, если что-то не так. Я склоняюсь к тому, чтобы сохранить то, чтоВы можете и позже определить, какой шаблон терпит неудачу; если вы предпочитаете отказаться от всей записи, если одна небольшая часть шаблона не работает, то это, вероятно, можно уменьшить до одного шаблона.)
patterns <- c(
"(?<=data )[0-9]+(?= is taken)",
"(?<=taken on )\\w+(?=, 2)",
"(?<=, )2[0-9]{3}\\b",
"(?<= at )\\w+(?=\n)",
"(?<=and is ).*(?=significant)",
"(?<=significant with).*"
)
lapply(patterns, function(ptn) {
trimws(sapply(regmatches(combined, gregexpr(ptn, combined, perl = TRUE)), `length<-`, 1))
})
# [[1]]
# [1] "1" "2" NA
# [[2]]
# [1] "Aug" "Sep" NA
# [[3]]
# [1] "2009" "2012" NA
# [[4]]
# [1] "UBC" "SFU" NA
# [[5]]
# [1] "" "not" "not"
# [[6]]
# [1] "p value <0.01" "p value > 0.06" NA
Этот вывод может быть легко записан, назван и структурирован с помощью чего-то вроде:
as.data.frame(setNames(
lapply(patterns, function(ptn) {
trimws(sapply(regmatches(combined, gregexpr(ptn, combined, perl = TRUE)), `length<-`, 1))
}),
c("number", "month", "year", "acronym", "not", "pvalue")),
stringsAsFactors = FALSE)
# number month year acronym not pvalue
# 1 1 Aug 2009 UBC p value <0.01
# 2 2 Sep 2012 SFU not p value > 0.06
# 3 <NA> <NA> <NA> <NA> not <NA>