ちょっと気になったので遊んでみたい。
日本郵便のwebサイトでは、全国の郵便番号と住所を組み合わせたデータを提供している ( http://www.post.japanpost.jp/zipcode/dl/roman-zip.html )。これをRで読み込んで、形態素解析で使われるMeCabをR上で扱えるようにしてくれる{RMeCab}パッケージを使ってごにょごにょしたい。今回はデータをとってきてこれから利用するファイルに編集するという準備編。使い方をわかっていないため、{RMeCab}はでてこない。ごめんなさい。
関数の呼び出しがパッケージ名を伴っていたり、文書中で{magrittr}と{pipeR}によるパイプ処理が混同しているが宗教的理由によるもの。
library(magrittr) # パイプ処理用
library(pipeR) # パイプ処理用
library(rvest) # スクレイピング、ファイルのダウンロード用
library(dplyr) # データ整形用
library(data.table) # ファイルの読み込み用
library(DT) # 表の出力用(おまけ。最後に使う)
ぽちっとリンクをクリックすればダウンロードされるけど、Rユーザーとしては一から十までRで済ませるという無駄なこだわりがあったのでRでやってみる。圧縮ファイルで提供されているので、今回は一時フォルダでファイルを展開する。
dl.file <- tempfile(fileext = ".zip")
download.file(url = "http://www.post.japanpost.jp/zipcode/dl/roman/ken_all_rome.zip",
destfile = dl.file)
unzip(zipfile = dl.file, exdir = tempdir(), overwrite = TRUE)
(file.path <- list.files(tempdir()) %>%
grep(pattern = ".csv", ., value = TRUE, ignore.case = TRUE) %>%
paste(tempdir(), ., sep = "/"))
## [1] "/var/folders/8f/s_lbgwks6q7g3lz52q93ngph0000gn/T//Rtmp2lra6I/KEN_ALL_ROME.CSV"
/var/folders/8f/s_lbgwks6q7g3lz52q93ngph0000gn/T//Rtmp2lra6I/KEN_ALL_ROME.CSVにファイルが置かれている。
日本郵便に掲載されているデータの利用上の注意には
ダウンロードデータは、CSV(可変長データ)形式のファイルをzip形式で圧縮して保存しております
全国一括のデータは12万件ある
と書かれている。ちょっと大きめのファイルサイズ(およそ1.6MBだそうで)なので、ファイルの読み込みには{data.table}のfread()を利用することにする。
df_post <- pipeline(
{
fread(input = file.path, header = FALSE)
# 例によって残念な感じなので列名を付け直す
setnames(c("郵便番号", "都道府県名", "市区町村名", "町域名",
"都道府県名roman", "市区町村名roman", "町域名roman"))
})
head(df_post, 3)
## 郵便番号 都道府県名
## 1: 0600000 \x96k\x8aC\x93\xb9
## 2: 0640941 \x96k\x8aC\x93\xb9
## 3: 0600041 \x96k\x8aC\x93\xb9
## 市区町村名
## 1: \x8eD\x96y\x8es\x81@\x92\x86\x89\x9b\x8b\xe6
## 2: \x8eD\x96y\x8es\x81@\x92\x86\x89\x9b\x8b\xe6
## 3: \x8eD\x96y\x8es\x81@\x92\x86\x89\x9b\x8b\xe6
## 町域名 都道府県名roman
## 1: \x88ȉ\xba\x82\u024cf\x8dڂ\xaa\x82Ȃ\xa2\x8fꍇ HOKKAIDO
## 2: \x88\xae\x83P\x8bu HOKKAIDO
## 3: \x91\xe5\x92ʓ\x8c HOKKAIDO
## 市区町村名roman 町域名roman
## 1: SAPPORO SHI CHUO KU IKANIKEISAIGANAIBAAI
## 2: SAPPORO SHI CHUO KU ASAHIGAOKA
## 3: SAPPORO SHI CHUO KU ODORIHIGASHI
ちなみに、fileEncodingを指定できるread.tableでは文字化けすることなくファイルを読み込める。が、いかんせん時間がかかるのでアレ。大容量データの読み込みに強いfreadを使い、読み込んでから文字化けを直したほうが速い。
読み込んだデータを確認してみる
dim(df_post)
## [1] 123803 7
dplyr::glimpse(df_post)
## Observations: 123803
## Variables:
## $ 郵便番号 (chr) "0600000", "0640941", "0600041", "0600042", "06408...
## $ 都道府県名 (chr) "\x96k\x8aC\x93\xb9", "\x96k\x8aC\x93\xb9", "\x96k\...
## $ 市区町村名 (chr) "\x8eD\x96y\x8es\x81@\x92\x86\x89\x9b\x8b\xe6", "\x...
## $ 町域名 (chr) "\x88ȉ\xba\x82\u024cf\x8dڂ\xaa\x82Ȃ\xa2\x8fꍇ", "\...
## $ 都道府県名roman (chr) "HOKKAIDO", "HOKKAIDO", "HOKKAIDO", "HOKKAIDO", "HO...
## $ 市区町村名roman (chr) "SAPPORO SHI CHUO KU", "SAPPORO SHI CHUO KU", "SAPP...
## $ 町域名roman (chr) "IKANIKEISAIGANAIBAAI", "ASAHIGAOKA", "ODORIHIGAS...
郵便番号の列も数値ではなく文字列として認識されている。文字化けしているが…。
ちょっとテコ入れ。
df_post %<>%
mutate_each(funs(iconv(x = ., from = "cp932", to = "utf8")), -contains("roman"))
head(df_post)
## 郵便番号 都道府県名 市区町村名 町域名
## 1: 0600000 北海道 札幌市 中央区 以下に掲載がない場合
## 2: 0640941 北海道 札幌市 中央区 旭ケ丘
## 3: 0600041 北海道 札幌市 中央区 大通東
## 4: 0600042 北海道 札幌市 中央区 大通西(1〜19丁目)
## 5: 0640820 北海道 札幌市 中央区 大通西(20〜28丁目)
## 6: 0600031 北海道 札幌市 中央区 北一条東
## 都道府県名roman 市区町村名roman 町域名roman
## 1: HOKKAIDO SAPPORO SHI CHUO KU IKANIKEISAIGANAIBAAI
## 2: HOKKAIDO SAPPORO SHI CHUO KU ASAHIGAOKA
## 3: HOKKAIDO SAPPORO SHI CHUO KU ODORIHIGASHI
## 4: HOKKAIDO SAPPORO SHI CHUO KU ODORINISHI(1-19-CHOME)
## 5: HOKKAIDO SAPPORO SHI CHUO KU ODORINISHI(20-28-CHOME)
## 6: HOKKAIDO SAPPORO SHI CHUO KU KITA1-JOHIGASHI
きちんと文字化けが直った。
次に、データの説明ページを見ると町域名という列には「以下に記載がない場合」という値が入ることがあるらしいので、それは欠損値として扱うように変換しておく。また、市区町村名および町域名に含まれる全角空白も余計なので除去しておく。
df_post %<>%
dplyr::mutate(町域名 = sub(pattern = "以下に掲載がない場合", replacement = NA, x = 町域名)) %>%
dplyr::mutate_each(funs(gsub("[[:space:]]", "", x = .)), c(市区町村名, 町域名))
head(df_post)
## 郵便番号 都道府県名 市区町村名 町域名
## 1: 0600000 北海道 札幌市中央区 NA
## 2: 0640941 北海道 札幌市中央区 旭ケ丘
## 3: 0600041 北海道 札幌市中央区 大通東
## 4: 0600042 北海道 札幌市中央区 大通西(1〜19丁目)
## 5: 0640820 北海道 札幌市中央区 大通西(20〜28丁目)
## 6: 0600031 北海道 札幌市中央区 北一条東
## 都道府県名roman 市区町村名roman 町域名roman
## 1: HOKKAIDO SAPPORO SHI CHUO KU IKANIKEISAIGANAIBAAI
## 2: HOKKAIDO SAPPORO SHI CHUO KU ASAHIGAOKA
## 3: HOKKAIDO SAPPORO SHI CHUO KU ODORIHIGASHI
## 4: HOKKAIDO SAPPORO SHI CHUO KU ODORINISHI(1-19-CHOME)
## 5: HOKKAIDO SAPPORO SHI CHUO KU ODORINISHI(20-28-CHOME)
## 6: HOKKAIDO SAPPORO SHI CHUO KU KITA1-JOHIGASHI
今後はこのファイルを使っていく予定なので、これを保存しておく。
write.table(df_post,
file = "jp_post_address.txt",
row.names = FALSE)
せっかくなので少しだけ。今回は住所データに対して「読み」を与えてみたい(ローマ字の列はあるけど、片仮名なり平仮名なりの読みがない。{Nippon}パッケージにあるのはkana2romanで、カナ→ローマ字に変換できても、ローマ字→カナはできない)。
さきほど保存したファイルを再度読み込む。(コンピュタ的な意味で)全部やると大変なので今回は札幌市の町域名に対し、「読み」を与えることを目的とする。
Pipe(fread("jp_post_address.txt", header = TRUE))$
# 北海道の札幌市内の行を抽出
filter(grep("北海道", 都道府県名))$
filter(grep("札幌市", 市区町村名))$
# 無駄な列は削除しておく
select(市区町村名, 町域名)$
# 市区町村名での「札幌市」というのは固定されている(例.札幌市中央区)ので、
# 「札幌市」は消す
mutate(市区町村名 = sub(pattern = "札幌市", "", x = 市区町村名))$
# 確認のために行数を数え、先頭行を表示する
.(? nrow(.))$
.(? head(.))$
# オブジェクトに保存する
.(~ df_post)$
# 再度、一時フォルダ内にファイルを保存する
write.csv(file = tempfile(fileext = ".txt"), row.names = FALSE)
次に保存したファイルをMeCabを使って処理。一時ファイルのパスは以下のように取得する。
(file.path <- list.files(tempdir()) %>%
grep(pattern = ".txt", ., value = TRUE, ignore.case = TRUE) %>%
paste(tempdir(), ., sep = "/"))
## [1] "/var/folders/8f/s_lbgwks6q7g3lz52q93ngph0000gn/T//Rtmp2lra6I/filef46598f128.txt"
MeCabには、文字列の読みを返すオプションがあるので、それを利用して
mecab ファイル名 -Oyomi | mecab -o sapporo_address_out.txt -Oyomi
とすればおk。
Pipe(fread("sapporo_address_out.txt", header = TRUE))$
.(setnames(., c("市区町村名読み", "町域名読み")))$
.(~ df_yomi)
最後に、元の住所データに読みデータを結合すれば完了。
Pipe(df_post)$
.(cbind(., df_yomi))$
.(~ df_post)
datatable(df_post)
fread()でのfileEncoding指定は需要があるみたいで、v.1.9.6のマイルストーンに加えられた。次回のバージョンアップに期待(現在GitHubからインストールできるバージョンは1.9.5)。
-> [R-Forge #4903] set encoding in fread · Issue #563 · Rdatatable/data.table