2016-05-13 130 views
0

我试着在DF提取名的某部分字符串

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 

我假设可以用sub来完成,就像我今天所学的那样,在第一个.之前如何提取这个字母,但是如何提取这个名字的“中间”部分呢? 我正在阅读sub解释和帮助,但我所有的试验结果只是将a的全名复制到c。 谢谢你的任何提示。

+0

您可以使用'子()'函数,如果要提取那封信。 –

+1

谢谢,substring()完成了这项工作!看起来好像比分:) :) – 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列。下面是一个使用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

使用regexprregmatches与回顾后和前瞻正则表达式。

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