2016-12-09 2 views
1

У меня есть данные, как показано ниже. Я хочу извлечь первый и последний год из каждой строки, которая называется my.string. Некоторые строки содержат только один год, а некоторые строки не содержат никаких лет. Никакие строки не содержат более двух лет. Я привел желаемый результат в объекте с именем desired.result ниже примера набора данных. Я использую R.экстракт нерегулярные числовые данные из строк

Если строка содержит два года в те годы, содержатся в части строки, которая выглядит следующим образом ga49.51 или ea22.24

Если строка содержит только один год в этом году, содержится в части строки, которая выглядит вот так: time11

Я знаю немного о regex, но эта проблема кажется слишком нерегулярной и сложной для меня, чтобы понять. Я даже не знаю, с чего начать. Спасибо за любой совет.

EDIT

Возможно удалить номера до первого двоеточия (:) и остальных чисел, что я хочу.

my.data <- read.table(text = ' 

       my.string cov1 cov2 

      42:Alpha:ga6.8 -0.1 2.2 
      43:Alpha:ga9.11 -2.5 0.6 
     44:Alpha:ga30.32 -1.3 0.5 
     45:Alpha:ga49.51 -2.5 0.6 
    50:Alpha:time1:ga.time -1.7 0.9 
    51:Alpha:time2:ga.time -1.5 0.8 
    52:Alpha:time3:ga.time -1.0 1.0 
      2:Beta:ea2.9 -1.7 0.6 
      3:Beta:ea17.19 -5.0 0.8 
      4:Beta:ea22.24 -6.4 1.0 
       8:Beta:as 0.2 0.6 
       9:Beta:sd 1.7 0.4 
    12:Beta:time1:ea.tim -2.6 1.8 
    13:Beta:time10:ea.ti -3.6 1.1 
    14:Beta:time11:ea.ti -3.1 0.7 

', header = TRUE, stringsAsFactors = FALSE, na.strings = "NA") 

desired.result <- read.table(text = ' 

       my.string cov1 cov2 time1 time2 

      42:Alpha:ga6.8 -0.1 2.2  6  8 
      43:Alpha:ga9.11 -2.5 0.6  9  11 
     44:Alpha:ga30.32 -1.3 0.5  30  32 
     45:Alpha:ga49.51 -2.5 0.6  49  51 
    50:Alpha:time1:ga.time -1.7 0.9  1  NA 
    51:Alpha:time2:ga.time -1.5 0.8  2  NA 
    52:Alpha:time3:ga.time -1.0 1.0  3  NA 
      2:Beta:ea2.9 -1.7 0.6  2  9 
      3:Beta:ea17.19 -5.0 0.8  17  19 
      4:Beta:ea22.24 -6.4 1.0  22  24 
       8:Beta:as 0.2 0.6  NA  NA 
       9:Beta:sd 1.7 0.4  NA  NA 
    12:Beta:time1:ea.tim -2.6 1.8  1  NA 
    13:Beta:time10:ea.ti -3.6 1.1  10  NA 
    14:Beta:time11:ea.ti -3.1 0.7  11  NA 

', header = TRUE, stringsAsFactors = FALSE, na.strings = "NA") 
+0

Какой язык программирования или язык сценариев используется для обработки текстового файла? – mangotang

+1

Можете ли вы показать пример вашего ожидаемого вывода на основе ввода образца? какая часть 'ga49.51' является годом? Какая часть 'time11' является годом (я угадываю' 11')? – mangotang

+0

'((?: Time | ga | ea) (? \ d +) (\. (? \ d +))?)' –

ответ

1

Вот регулярное выражение, которое будет извлекать любого из этих двух типов, и выводить их на другие столбцы в конце строки:

Поиск: .*(?:time(\d+)|(?:[ge]a)(\d+)\.(\d+)).*

Заменить: $0\t$1\t$2\t$3

Поломка:

  • .*(?: ... ).* гарантирует, что вся линия согласована, и использует, не захватив группу для основного чередования
  • time(\d+): это первая половина чередования, захватывая любые цифры после «времени»
  • (?:[ge]a)(\d+)\.(\d+): вторая половина чередования соответствует «ga» или «ea», за которой следуют два набора цифр, каждая в своей собственной группе захвата
  • Замена: $0 помещает всю строку назад. Каждая из других групп захвата добавляется вместе с вкладками.

See regex101 example

2

Я предлагаю использовать stringr библиотеку, чтобы извлечь необходимые вам данные, так как он обрабатывает значения NA лучше, а также позволяет использовать с ограничениями-ширина просмотра назад:

> library(stringr) 
> my.data$time1 <- str_extract(my.data$my.string, "(?<=time)\\d+|(?<=\\b[ge]a)\\d+") 
> my.data$time2 <- str_extract(my.data$my.string, "(?<=\\b[ge]a\\d{1,100}\\.)\\d+") 
> my.data 
       my.string cov1 cov2 time1 time2 
1   42:Alpha:ga6.8 -0.1 2.2  6  8 
2   43:Alpha:ga9.11 -2.5 0.6  9 11 
3  44:Alpha:ga30.32 -1.3 0.5 30 32 
4  45:Alpha:ga49.51 -2.5 0.6 49 51 
5 50:Alpha:time1:ga.time -1.7 0.9  1 <NA> 
6 51:Alpha:time2:ga.time -1.5 0.8  2 <NA> 
7 52:Alpha:time3:ga.time -1.0 1.0  3 <NA> 
8   2:Beta:ea2.9 -1.7 0.6  2  9 
9   3:Beta:ea17.19 -5.0 0.8 17 19 
10   4:Beta:ea22.24 -6.4 1.0 22 24 
11    8:Beta:as 0.2 0.6 <NA> <NA> 
12    9:Beta:sd 1.7 0.4 <NA> <NA> 
13 12:Beta:time1:ea.tim -2.6 1.8  1 <NA> 
14 13:Beta:time10:ea.ti -3.6 1.1 10 <NA> 
15 14:Beta:time11:ea.ti -3.1 0.7 11 <NA> 

1 регулярное выражение:

  • (?<=time)\\d+ - 1+ цифры, которые имеют time перед ними
  • | - или
  • (?<=\\b[ge]a)\\d+ - 1+ цифры, которые имеют ge или ea` как целое слово перед

Второе выражение матчи:

  • (?<=\\b[ge]a\\d{1,100}\\.) - проверить, соответствует ли текущему положению ge или ea в качестве целого слова, за которым следуют от 1 до 100 цифры (я считаю, что должно быть достаточно для сценария, 100-разрядные куски вряд ли ожидается здесь, вы можете даже уменьшить значение), а затем .
  • \\d+ - 1+ цифры