2016-05-13 2 views
0

Im пытается извлечь определенную часть имен в колонке DFExtract определенную часть названия в строке

DF 
a   b 
a.b.c_tot 1 
b.c.d_tot 2 
d.e.g_tot 3 

Мне нужно извлечь письмо между . и _tot, так что

DF 
a   b c 
a.b.c_tot 1 c 
b.c.d_tot 2 d 
d.e.g_tot 3 g 

I предположим, что это можно сделать с помощью sub, так как я узнал сегодня, как извлечь письмо перед первым ., но как извлечь «среднюю» часть имени? Я читал sub объяснение и помощь, но все мои результаты испытаний просто копируют полное имя a в c. Спасибо за любые советы.

+0

Вы можете использовать 'подстрока()' функцию, если вы хотите, чтобы извлечь эту букву. –

+1

Спасибо, подстрока() сделала работу! и кажется намного легче, чем sub :) – HoHoHo

ответ

4

Мы можем позвонить sub(), чтобы соответствовать всей строке, начиная с (1) любого числа любых символов, затем (2) буквальной точки, затем (3) использовать группу захвата для захвата следующего символа, затем (4) буква _tot. Затем мы можем использовать атом обратной линии \1 (с обратным слэшем, соответствующим обратным слэшам, экранированным в соответствии с правилами кодирования строки R), чтобы заменить всю строку на захваченный символ.

DF$c <- sub('^.*\\.(.)_tot$','\\1',DF$a); 
DF; 
##   a b c 
## 1 a.b.c_tot 1 c 
## 2 b.c.d_tot 2 d 
## 3 d.e.g_tot 3 g 

Да, я вижу проблему; если DF$a должны были содержать значения, которые не соответствуют ожидаемому шаблону, вызов sub() передаст их в новый столбец DF$c. Вот Hacky решение, используя Perl branch reset особенность:

DF <- data.frame(a=c('a.b.c_tot','b.c.d_tot','d.e.g_tot','non-matching'),b=c(1L,2L,3L,4L),stringsAsFactors=F); 
DF$c <- sub(perl=T,'(?|^.*\\.(.)_tot$|^.*$())','\\1',DF$a); 
DF; 
##    a b c 
## 1 a.b.c_tot 1 c 
## 2 b.c.d_tot 2 d 
## 3 d.e.g_tot 3 g 
## 4 non-matching 4 

Вот лучшее решение, включая хранение регулярное выражение в переменной заранее, и с помощью grepl() и replace() заменить значения несовпадающих с NA до вызова sub():

re <- '^.*\\.(.)_tot$'; 
DF$c <- sub(re,'\\1',replace(DF$a,!grepl(re,DF$a),NA)); 
DF; 
##    a b c 
## 1 a.b.c_tot 1 c 
## 2 b.c.d_tot 2 d 
## 3 d.e.g_tot 3 g 
## 4 non-matching 4 <NA> 
+0

К сожалению, он возвращает мне все имя. – HoHoHo

+0

Спасибо, сейчас работает. да, это была моя ошибка. – HoHoHo

2

Использование regexpr и regmatches с просмотром назад и опережения регулярное выражение.

x <- c("a.b.c_tot", "b.c.d_tot", "d.e.g_tot") 
regmatches(x, regexpr("(?<=\\.).(?=_tot)", x, perl = TRUE)) 
#[1] "c" "d" "g" 
2

Мы можем использовать str_extract

library(stringr) 
DF$c <- str_extract(DF$a, "\\w(?=_tot)") 
DF$c 
#[1] "c" "d" "g" 
+0

Спасибо, это, похоже, делает работу! :) – HoHoHo

Смежные вопросы