Подтвердить что ты не робот

Строна, разбитая условиями в 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"
4b9b3361

Ответ 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"