2017-04-06 18 views
1

我正在使用grep来整理一些地址数据,我的目标特别是在给定的记录和列中识别街道/大道/道路名称等,这已经被空间分割成单个词语的以下变量tempval,例如:R:使用grep按重要性排序查找一个或几个匹配项

R > tempval 
[1] "38" "WILLOW" "PARK" 

我用下面的语句来发现其中一些将按照街道名称可能是一句话:

stID <- grep("STREET|\\bST\\b|AVENUE|\\bAVE\\b|\\bAV\\b|WAY|BOULEVARD|\\bBD\\b|ROAD|\\bRD\\b|PLACE|\\bPL\\b|ESPLANADE|TERRACE|PARADE|DRIVE|\\bDR\\b|\\bPARK\\b|LANE|CRESCENT|\\bCOURT\\b|b\\CRES\\b", tempval, ignore.case = T) 

R > stID 
[1] 3 

Th是好的,我知道“PARK”是第三个元素,之前会有什么是我的街道号码和名称。

然而,当有多个匹配如此length(stID) > 1,例如一个问题出现了:所以在这里

R > tempval 
[1] "38" "PARK" "ST" 

,我得到

R > stID 
[1] 2 3 

如何获得R返回只有一个匹配,在重要性顺序(我将字符串放在grep模式中的顺序)?换句话说,如果R找到“ST”和“PARK”,“ST”比“PARK”更重要,因此只返回stID = 3

回答

3

使用grep是非常危险的,因为您的grep即使在需要优先考虑的情况下也会在“街头生活公园”上尝试使用时返回“streetlife”作为街道名称(它会在“街头生活”)。

因此,我建议您改用match。将所有内容转换为较低值,并使用具有重要顺序值的向量。然后,您可以使用match查看x中的哪些位置与该向量匹配。现在,你必须寻找不是NA的第一个值,你就大功告成了:

checkstreet <- function(x){ 
    x <- tolower(x) 
    thenames <- c("street","st","avenue","ave","av", 
       "way","boulevard", "bd", "road", "rd", 
       "place", "pl", "esplanade","terrace","parade", 
       "drive","dr","park","lane","crescent","court", 
       "cres") 

    id <- match(thenames, x) 
    id[!is.na(id)][1] 
} 

给出:

> tmpval <- c("38","park","street") 
> checkstreet(tmpval) 
[1] 3 
> tmpval <- c("44","Average","Esplanade") 
> checkstreet(tmpval) 
[1] 3 

如果你坚持使用grep和继续使用的\\b您的Word边界,您可以使用相同的逻辑,但使用which.min此时:

checkstreet <- function(x){ 
    x <- tolower(x) 
    thenames <- c("street","st","avenue","ave","av", 
       "way","boulevard", "bd", "road", "rd", 
       "place", "pl", "esplanade","terrace","parade", 
       "drive","dr","park","lane","crescent","court", 
       "cres") 

    which.min(lapply(x,grep,thenames)) 
} 
+0

非常好,谢谢! grep是第一个想到的工具,但是按照重要性顺序使用与字符串矢量匹配是完全有意义的。 – Neodyme

1

你可以通过匹配每个搜索词individua的做在一个循环中,然后对比赛进行得分评分,给出比较高的分数以便放在搜索列表中较早的比赛中:

## Vector of search terms: 
matchVec <- strsplit("STREET|\\bST\\b|AVENUE|\\bAVE\\b|\\bAV\\b|WAY|BOULEVARD|\\bBD\\b|ROAD|\\bRD\\b|PLACE|\\bPL\\b|ESPLANADE|TERRACE|PARADE|DRIVE|\\bDR\\b|\\bPARK\\b|LANE|CRESCENT|\\bCOURT\\b|b\\CRES\\b", "\\|")[[1]] 

## Function to determine score of the match: 
scoreMatch <- function(myString, matchVec){ 
    ## Position of matches in the search list: 
    position <- which(vapply(matchVec, function(matchStr) grepl(pattern = matchStr, x = myString), 
        logical(1))) 
    ## Score: First search term gets the highest score, second gets second 
    ## highest score etc. No match = score 0: 
    score <- ifelse(length(position) > 0, length(matchVec) - position + 1, 0) 
} 

## Determine score of each element/word in your vector: 
scoreVec <- vapply(tempval, function(x) scoreMatch(x, matchVec), numeric(1)) 

## Find index with the highest score: 
stID <- which.max(scoreVec) 
+0

我看到你在这里尝试的,但是这可以用一行代码实际完成,使用'lapply'和'which.min'(看我的答案) –

+0

是的,你的解决方案非常优雅。不过,checkstreet('grep'-version)定义的最后一行不应该是'which.min(lapply(x,grep,thenames))'吗? – ikop

+0

好抓,thx! –

相关问题