ここで英国政府が提供する正規表現を使用して、R の住所文字列から英国の郵便番号を抽出しようとしています。
これが私の機能です:
address_to_postcode <- function(addresses) {
# 1. Convert addresses to upper case
addresses = toupper(addresses)
# 2. Regular expression for UK postcodes:
pcd_regex = "[Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([A-Za-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z])))) {0,1}[0-9][A-Za-z]{2})"
# 3. Check if a postcode is present in each address or not (return TRUE if present, else FALSE)
present <- grepl(pcd_regex, addresses)
# 4. Extract postcodes matching the regular expression for a valid UK postcode
postcodes <- regmatches(addresses, regexpr(pcd_regex, addresses))
# 5. Return NA where an address does not contain a (valid format) UK postcode
postcodes_out <- list()
postcodes_out[present] <- postcodes
postcodes_out[!present] <- NA
# 6. Return the results in a vector (should be same length as input vector)
return(do.call(c, postcodes_out))
}
ガイダンス ドキュメントによると、この正規表現が探すロジックは次のとおりです。
"GIR 0AA" または 1 文字の後に 1 つまたは 2 つの数字が続く、または 1 つの文字の後に ABCDEFGHJ KLMNOPQRSTUVWXY (つまり、I ではない) のいずれかでなければならない 2 番目の文字が続き、その後に 1 つまたは 2 つの数字が続く、または 1 つの文字の後に 1 つが続く数字の後に別の文字または 2 部構成の郵便番号。最初の部分は 1 文字で、2 番目の文字は ABCDEFGH JKLMNOPQRSTUVWXY (つまり、I ではない) のいずれかで、その後に 1 つの数字とオプションでさらに文字が続きます。 AND 2 番目の部分 (最初の部分からスペースで区切られている) は、1 つの数字の後に 2 つの文字が続く必要があります。大文字と小文字の組み合わせが許可されています。注: 長さは正規表現によって決定され、2 ~ 8 文字です。
^
私の問題は、アンカーとなしで正規表現を使用すると、このロジックが完全に保持されないこと$
です (郵便番号が住所文字列内のどこにでもある可能性があるため、このシナリオで行う必要があります)。私が苦労しているのは、部分的な (完全ではなく) 文字列一致で各セグメントの順序と文字数を保持する方法です。
次の例を検討してください。
> address_to_postcode("1A noplace road, random city, NR1 2PK, UK")
[1] "NR1 2PK"
ガイドラインの論理によれば、郵便番号の 2 番目の文字を「z」にすることはできません (その他の例外もあります)。ただし、「z」を追加するとどうなるか見てください。
> address_to_postcode("1A noplace road, random city, NZ1 2PK, UK")
[1] "Z1 2PK"
... 一方、この場合、出力はNA
.
アンカーを追加しても(別の使用例では)、「z」が間違った場所にあるにもかかわらず受け入れられるため、役に立たないようです。
> grepl("^[Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([A-Za-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z])))) {0,1}[0-9][A-Za-z]{2})$", "NZ1 2PK")
[1] TRUE
2 つの質問:
- 正規表現の論理を誤解していて、
- そうでない場合、どうすれば修正できますか (つまり、指定された文字と文字の範囲が正規表現内の位置に限定されないのはなぜですか)?