Мы можем позвонить 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>
Вы можете использовать 'подстрока()' функцию, если вы хотите, чтобы извлечь эту букву. –
Спасибо, подстрока() сделала работу! и кажется намного легче, чем sub :) – HoHoHo