【发布时间】:2016-01-26 00:02:57
【问题描述】:
是否有更“r”的方式从 data.table 中的列中的较长字符串中提取两个有意义的字符?
我有一个 data.table,其中有一列包含“学位字符串”...某人获得的学位和毕业年份的简写代码。
> srcDT<- data.table(
alum=c("Paul Lennon","Stevadora Nicks","Fred Murcury"),
degree=c("W72","WG95","W88")
)
> srcDT
alum degree
1: Paul Lennon W72
2: Stevadora Nicks WG95
3: Fred Murcury W88
我需要从学位中提取年份的数字,并将其放入一个名为“degree_year”的新列中
没问题:
> srcDT[,degree_year:=substr(degree,nchar(degree)-1,nchar(degree))]
> srcDT
alum degree degree_year
1: Paul Lennon W72 72
2: Stevadora Nicks WG95 95
3: Fred Murcury W88 88
要是一直这么简单就好了。 问题是,度数字符串有时看起来像上面那样。更多时候,它们看起来像这样:
srcDT<- data.table(
alum=c("Ringo Harrison","Brian Wilson","Mike Jackson"),
degree=c("W72 C73","WG95 L95","W88 WG90")
)
我只对我关心的字符旁边的 2 个数字感兴趣:W 和 WG(如果 W 和 WG 都在,我只关心 WG)
我是这样解决的:
x <-srcDT$degree ##grab just the degree column
z <-character() ## create an empty character vector
degree.grep.pattern <-c("WG[0-9][0-9]","W[0-9][0-9]")
## define a vector of regex's, in the order
## I want them
for(i in 1:length(x)){ ## loop thru all elements in degree column
matched=F ## at the start of the loop, reset flag to F
for(j in 1:length(degree.grep.pattern)){
## loop thru all elements of the pattern vector
if(length(grep(degree.grep.pattern[j],x[i]))>0){
## see if you get a match
m <- regexpr(degree.grep.pattern[j],x[i])
## if you do, great! grab the index of the match
y<-regmatches(x[i],m) ## then subset down. y will equal "WG95"
matched=T ## set the flag to T
break ## stop looping
}
## if no match, go on to next element in pattern vector
}
if(matched){ ## after finishing the loop, check if you got a match
yr <- substr(y,nchar(y)-1,nchar(y))
## if yes, then grab the last 2 characters of it
}else{
#if you run thru the whole list and don't match any pattern at all, just
# take the last two characters from the affilitation
yr <- substr(x[i],nchar(as.character(x[i]))-1,nchar(as.character(x[i])))
}
z<-c(z,yr) ## add this result (95) to the character vector
}
srcDT$degree_year<-z ## set the column to the results.
> srcDT
alum degree degree_year
1: Ringo Harrison W72 C73 72
2: Brian Wilson WG95 L95 95
3: Mike Jackson W88 WG90 90
这行得通。 100% 的时间。没有错误,没有错配。 问题是:它无法扩展。给定一个有 10k 行或 100k 行的数据表,它确实会变慢。
有没有更聪明、更好的方法来做到这一点?这个解决方案对我来说非常“C”。不是很“R”。
有改进的想法?
注意:我举了一个简化的例子。在实际数据中,大约有 30 种不同的可能的学位组合,结合不同的年份,大约有 540 种不同的学位字符串组合。 另外,我给了 degree.grep.pattern,只有 2 个模式可以匹配。在我做的实际工作中,有 7 或 8 种模式可以匹配。
【问题讨论】:
-
我想你想要
WG,因为它是最近的? 2001 年授予的学位是W01吗?每个alum的度数是否相同(不,我假设)?
标签: regex r data.table