Строна, разбитая условиями в R
У меня есть это mystring
с разделителем _
. Условие здесь: если есть два или более разделителей, я хочу разделить на втором разделителе, и если есть только один разделитель, я хочу разделить на ".Recal"
и получить result
, как показано ниже.
mystring<-c("MODY_60.2.ReCal.sort.bam","MODY_116.21_C4U.ReCal.sort.bam","MODY_116.3_C2RX-1-10.ReCal.sort.bam","MODY_116.4.ReCal.sort.bam")
результат
"MODY_60.2" "MODY_116.21" "MODY_116.3" "MODY_116.4"
Ответы
Ответ 1
Вы можете сделать это, используя gsubfn
library(gsubfn)
f <- function(x,y,z) if (z=="_") y else strsplit(x, ".ReCal", fixed=T)[[1]][[1]]
gsubfn("([^_]+_[^_]+)(.).*", f, mystring, backref=2)
# [1] "MODY_60.2" "MODY_116.21" "MODY_116.3" "MODY_116.4"
Это позволяет использовать случаи, когда у вас более двух "_", и вы хотите разделить на второй, например,
mystring<-c("MODY_60.2.ReCal.sort.bam",
"MODY_116.21_C4U.ReCal.sort.bam",
"MODY_116.3_C2RX-1-10.ReCal.sort.bam",
"MODY_116.4.ReCal.sort.bam",
"MODY_116.4_asdfsadf_1212_asfsdf",
"MODY_116.5.ReCal_asdfsadf_1212_asfsdf", # split by second "_", leaving ".ReCal"
"MODY")
gsubfn("([^_]+_[^_]+)(.).*", f, mystring, backref=2)
# [1] "MODY_60.2" "MODY_116.21" "MODY_116.3" "MODY_116.4"
# [5] "MODY_116.4" "MODY_116.5.ReCal" "MODY"
В функции f
, x
- это исходная строка, следующие соответствия - y
и z
. Таким образом, если z
не является "_", то оно продолжается с разбиением на альтернативную строку.
Ответ 2
С пакетом stringr
:
str_extract(mystring, '.*?_.*?(?=_)|^.*?_.*(?=\\.ReCal)')
[1] "MODY_60.2" "MODY_116.21" "MODY_116.3" "MODY_116.4"
Он также работает с более чем двумя разделителями.
Ответ 3
Perl/PCRE имеет функцию branch reset, которая позволяет повторно использовать номер группы при захвате групп в разных альтернативах и рассматривается как одна группа захвата.
IMO, эта функция элегантна, когда вы хотите предоставить различные альтернативы.
x <- c('MODY_60.2.ReCal.sort.bam', 'MODY_116.21_C4U.ReCal.sort.bam',
'MODY_116.3_C2RX-1-10.ReCal.sort.bam', 'MODY_116.4.ReCal.sort.bam',
'MODY_116.4_asdfsadf_1212_asfsdf', 'MODY_116.5.ReCal_asdfsadf_1212_asfsdf', 'MODY')
sub('^(?|([^_]*_[^_]*)_.*|(.*)\\.ReCal.*)$', '\\1', x, perl=T)
# [1] "MODY_60.2" "MODY_116.21" "MODY_116.3" "MODY_116.4"
# [5] "MODY_116.4" "MODY_116.5.ReCal" "MODY"
Ответ 4
gsub('^(.*\\.\\d+).*','\\1',mystring)
[1] "MODY_60.2" "MODY_116.21" "MODY_116.3" "MODY_116.4"
Ответ 5
^([^_\\n]*_[^_\\n]*)(?:_.*|\\.ReCal[^_]*)$
Вы можете просто использовать gsub
, не используя какое-либо сложное регулярное выражение. Просто замените на \\1
. См. демонстрацию.
https://regex101.com/r/wL4aB6/1
Ответ 6
Немного дольше, но вам нужно меньше знаний о регулярных выражениях:
library(stringr)
indx <- str_locate_all(mystring, "_")
for (i in seq_along(indx)) {
if (nrow(indx[[i]]) == 1) {
mystring[i] <- strsplit(mystring[i], ".ReCal")[[1]][1]
} else {
mystring[i] <- substr(mystring[i], start = 1, stop = indx[[i]][2] - 1)
}
}
Ответ 7
gregexpr
может искать шаблон в строках и определять местоположение.
Сначала мы используем gregexpr
, чтобы найти местоположение всех _
в каждом элементе mystring
. Затем мы перебираем этот вывод и извлекаем индекс секунды _
в каждом элементе mystring
. Если второго _
нет, он вернет NA
(см. inds
в приведенном ниже примере).
После этого мы можем либо извлечь соответствующую часть, используя substr
на основе извлеченного индекса, либо, если есть NA
, мы можем разделить строку в .ReCal
и сохранить только первую часть.
inds = sapply(gregexpr("_", mystring, fixed = TRUE), function(x) x[2])
ifelse(!is.na(inds),
substr(mystring, 1, inds - 1),
sapply(strsplit(mystring, ".ReCal"), '[', 1))
#[1] "MODY_60.2" "MODY_116.21" "MODY_116.3" "MODY_116.4"