cucumber flesh

Rを中心としたデータ分析・統計解析らへんの話題をしていくだけ

郵便番号データの操作と祝日判定の機能を追加したzipangu v0.2.0を公開

昨年バージョン0.1.0をリリースした、日本人が扱う住所や年号、漢数字のデータ操作を楽にするRパッケージ、{zipangu}に新しい機能を追加し、バージョン0.2.0としてCRANに登録しました。この記事では0.2.0で扱える新機能を紹介します。表題の通り、郵便番号データの操作と、祝日の判定機能がメインです。

uribo.hatenablog.com

https://cran.r-project.org/web/packages/zipangu/news/news.html

library(zipangu)
library(dplyr, warn.conflicts = FALSE)
packageVersion("zipangu")
## [1] '0.2.0'

1. 郵便番号

日本郵便が住所別の郵便番号データを公開しています。このファイルをRに取り込む関数を用意しました。郵便番号ファイルは頻繁に更新されるため、ローカルでのパス指定だけでなくURLによるファイル読み込みも可能となっています。

公開されるファイルには、住所の表記に関していくつかの種類や事業所を含めたデータがありますが、こうしたバリエーションにも対応します。具体的には、type引数に対象ファイルを元に以下の値を与えます。

  • oogaki: 読み仮名データの促音・拗音を小書きで表記しないもの
  • kogaki: 読み仮名データの促音・拗音を小書きで表記するもの
  • roman: 読み仮名データがローマ字
  • jigyosyo: 事業所の個別郵便番号
# パッケージに含まれるサンプルデータを読み込みます
zipcode_file <- 
  system.file("zipcode_dummy/13TOKYO_kogaki.CSV", package = "zipangu")
df_oogaki <- 
  zipangu::read_zipcode(path = zipcode_file, type = "oogaki")
glimpse(df_oogaki)
## Observations: 1
## Variables: 15
## $ jis_code             <chr> "13101"
## $ old_zip_code         <chr> "100"
## $ zip_code             <chr> "1000001"
## $ prefecture_kana      <chr> "トウキヨウト"
## $ city_kana            <chr> "チヨダク"
## $ street_kana          <chr> "チヨダ"
## $ prefecture           <chr> "東京都"
## $ city                 <chr> "千代田区"
## $ street               <chr> "千代田"
## $ is_street_duplicate  <dbl> 0
## $ is_banchi            <dbl> 0
## $ is_cyoumoku          <dbl> 0
## $ is_zipcode_duplicate <dbl> 0
## $ status               <dbl> 0
## $ modify_type          <dbl> 0

URLを直接指定する際は type の指定が不要です。

read_zipcode("https://www.post.japanpost.jp/zipcode/dl/jigyosyo/zip/jigyosyo.zip")

read_zipcode() では圧縮ファイルをRに読み込みますが、dl_zipcode_file()によりファイルをダウンロードしておくことも可能です。

dl_zipcode_file(path = "https://www.post.japanpost.jp/zipcode/dl/oogaki/zip/02aomori.zip")

このほか、is_zipcode()zipcode_spacer() を用意しました。前者は入力が7桁の郵便番号かどうかをチェック、後者は郵便番号に使われるハイフンを追加・除去するちょっとした関数です。

is_zipcode(7000027)
## [1] TRUE
is_zipcode("700-0027")
## [1] TRUE
zipcode_spacer("3050053")
## [1] "305-0053"
# ハイフンを取り除く際は remove = TRUE を指定します
zipcode_spacer("305-0053", remove = TRUE)
## [1] "3050053"

郵便番号データの公開は貴重ですが「KEN_ALL.csvの闇」と噂される記録のされ方で、実際に扱う場合は処理が面倒です。こうしたデータをtidyにする試みについては前回書いたとおりです。

uribo.hatenablog.com

この課題に関して、id:yutannihilation さんにも取り込んでいただきました。

github.com

機能要望として郵便番号の検索が提案されています。どういう形でデータを整形・表示すれば良いのかについて、議論の余地が残ると判断し、完成に至っていません。

2. 日本の祝日

祝日(国民の休日)判定のための関数を用意しました。これらは{zipangu}パッケージの開発のきっかけとなる{Nippon}で提供されていた機能でもあります。最初のリリースでは実装が追いついていませんでしたので、当初の目的を果たせました(拍手)。

入力に与えた日付が祝日かを返却する is_jholiday() と その年の祝日を調べる jholiday() があります。

Nippon::is.jholiday(as.Date("2019-12-23"))
## [1] TRUE
is_jholiday(date = as.Date("2019-12-23"))
## [1] FALSE
# 今年の祝日を調べる
jholiday(year = 2020, lang = "jp")
## $元日
## [1] "2020-01-01"
## 
## $成人の日
## [1] "2020-01-13"
## 
## $建国記念の日
## [1] "2020-02-11"
## 
## $天皇誕生日
## [1] "2020-02-23"
## 
## $春分の日
## [1] "2020-03-20"
## 
## $昭和の日
## [1] "2020-04-29"
## 
## $憲法記念日
## [1] "2020-05-03"
## 
## $みどりの日
## [1] "2020-05-04"
## 
## $こどもの日
## [1] "2020-05-05"
## 
## $海の日
## [1] "2020-07-23"
## 
## $スポーツの日
## [1] "2020-07-24"
## 
## $山の日
## [1] "2020-08-10"
## 
## $敬老の日
## [1] "2020-09-21"
## 
## $秋分の日
## [1] "2020-09-22"
## 
## $文化の日
## [1] "2020-11-03"
## 
## $勤労感謝の日
## [1] "2020-11-23"
# 天皇誕生日は時代に合わせて変更されます
jholiday_spec(year = 1988, name = "天皇誕生日", lang = "jp")
## [1] "1988-04-29"
jholiday_spec(2018, "天皇誕生日", lang = "jp")
## [1] "2018-12-23"
jholiday_spec(2020, "天皇誕生日", lang = "jp")
## [1] "2020-02-23"

大元の祝日の一覧は内閣府が配布するcsvファイルを参照しています。2020年1月現在に決まっているものなので、将来、祝日の変更があった際はデータを更新しなくてはいけなくなりますが、アーカイブされてしまった{Nippon}で用意されていた機能を復活させたこと、天皇の即位や東京オリンピック開催に関する2019、2020年の祝日の変更に対応できた点は良かったと思います。

また、ここでの作業の副産物として「ある月の第二月曜日」などを調べるための関数 find_date_by_wday() ができました。年 (year)、月 (month)、曜日 (wday… デフォルトでは日曜日が1)、週番号 (ordinal) を指定して実行します。

find_date_by_wday(year = 2020, month = 1, wday = 2, ordinal = 2)
## [1] "2020-01-13"

不具合や新機能の提案はGitHub issuesまたは Twitter @u_ribo までお願いします。

郵便番号データをtidyにする挑戦

日本人が頻繁に遭遇するデータ操作を効率的に行うための{zipangu}パッケージ、想定よりも多くの人が喜んでくれたようで、私としても嬉しく思っています。

記事の最後にプロジェクトの協力者を募集したら数名からの反応があり、また新機能の要望も挙げられました。 ありがとうございます。

さて、次のリリースでは郵便番号の処理を効率的に行う機能を実装する計画でいます。 具体的には日本郵便が提供する郵便番号csvファイル(以下、郵便番号データ)をRで読み込む関数と、郵便番号の検索および住所情報を返却する機能です。

github.com

Add japan zip-code utility functions by uribo · Pull Request #6 · uribo/zipangu · GitHub

ファイルの読み込みに関してはすでにmasterブランチへマージされています。 そして郵便番号検索の方もここで読み込んだファイルを利用すれば良かろうと思っていたのですが、こんなご意見をいただきました。

どうもこの郵便番号データには問題があるそうです。探ってみましょう。

install.packages("remotes")
remotes::install_github("uribo/zipan")
library(dplyr)
library(zipangu)
library(stringr)
# read_zipcode() が郵便番号データを読み込むための関数です。
# 提供されている3種類(読み仮名データの促音・拗音を小書きで表記しないもの、読み仮名データの促音・拗音を小書きで表記するもの、ローマ字)の住所の表記形式、事業所のcsvファイルに対応します
# path引数にzipファイルが置かれるURLまたはコンピュータ上のファイルパスを指定します
df <- 
    read_zipcode(path = "https://www.post.japanpost.jp/zipcode/dl/oogaki/zip/ken_all.zip",
               type = "kogaki") %>% 
  # 市区町村コード、郵便番号、住所に関する列、重複の判定のために「丁目を有する町域の場合の表示」の列を選んでおきます
  select(jis_code, zip_code, prefecture, city, street, is_cyoumoku)

例えば郵便番号066-0005のレコードを検索すると次のように3件のデータが返却されます。同じ郵便番号、市町村なのになぜ?となりますが、street列で表示している町域名がおかしいことに気がつきます。

df %>% 
  filter(zip_code == "0660005")
jis_code zip_code prefecture city street is_cyoumoku
01224 0660005 北海道 千歳市 協和(88−2、271−10、343−2、404−1、427− 0
01224 0660005 北海道 千歳市 3、431−12、443−6、608−2、641−8、814、842− 0
01224 0660005 北海道 千歳市 5、1137−3、1392、1657、1752番地) 0

なんと、これは郵便番号データ番号ファイルの仕様です。データの説明書きに次の記述があります。

全角となっている町域部分の文字数が38文字を越える場合、また半角となっているフリガナ部分の文字数が76文字を越える場合は、複数レコードに分割しています

このままでは検索用の関数を用意する際に問題になります。

また、これ以外にも数々の問題点があり、これまでに多くの方が記事にまとめてくださっています。 この行の分割をはじめとしていくつかの問題への対策方法が書かれている記事も見受けられました。

bleis-tift.hatenablog.com

togetter.com

一方で、次の2点に関する具体的な処理方法については見つけることができませんでした。

  • 藤野(400、400−2番地) など「、」で複数の住所がある –> 藤野400藤野400-2番地 の行を分ける
  • 大通西(1〜19丁目) のように住所が省略される –> 大通西1丁目大通西2丁目大通西3丁目、… 大通西19丁目 を独立させる

以下に示すように、元のデータはtidy1ではありません。 扱うデータがtidyであることを心がける身としては放っては置けない問題です。

df %>% 
  filter(zip_code %in% c("0050840", "0600042"))
jis_code zip_code prefecture city street is_cyoumoku
01101 0600042 北海道 札幌市中央区 大通西(1〜19丁目) 1
01106 0050840 北海道 札幌市南区 藤野(400、400−2番地) 0

このデータをtidyにするならこうかなと思います (大通西の住所は一部省略)

jis_code zip_code prefecture city street
01106 0050840 北海道 札幌市南区 藤野400
01106 0050840 北海道 札幌市南区 藤野400-2番地
01101 0600042 北海道 札幌市中央区 大通西1丁目
01101 0600042 北海道 札幌市中央区 大通西2丁目

そんなわけで前置きが長くなりましたが、こうした問題の解決に取り組んでいます。 いくつかの課題に関しては解決できそうと目処が立つ、一方で完璧には程遠いことを感じてきたので一旦整理しておきます。

目次

  • 住所の重複と複数行に分割される問題への対処
  • 「、」で区切られた住所を分割する
    • 京都市内の通り名
    • 複雑な町域名
  • 「〜」によって省略される住所を復元する
  • 残った課題

  1. 効果的なデータ分析を行いやすくするためのデータの持ち方を指す概念。参考: https://www.jstatsoft.org/article/view/v059i10

続きを読む

ハドリーに倣い、コンソールにブランチ名を表示&フォントを変える

何事も形から入るタイプの @u_ribo です。ネットストーキングに定評があります。

皆さんには憧れの人はいますか? 憧れの人が使っているものは、なぜか格好良く見えたり、自分も興味を抱くようになった経験はないでしょうか。

さて、憧れの人であるHadleyが登壇していた動画をYouTubeで見ていると気になる箇所がありました。この辺りです(次の動画の再生箇所)。

...プロンプト 1 にGitブランチ名を表示させるの格好いい

見た目重視の私は、憧れの人Hadley WickhamやRStudioチームが使っているものをすぐに真似したくなる癖があります。

調べてみると、どうもHadleyは自作関数でこの機能を実現可能にしていたようです。 そしてこの機能を含め、コンソールにさまざまな情報を表示させるのはpromptパッケージを使うと簡単に導入できることがわかりました。

github.com

MaraさんもTwitterで紹介されていました。

雰囲気はこのつぶやきのGif画像を見たらわかると思います。そんなわけで今回は実際に promptパッケージを使ってコンソールをカスタマイズする話です。

動機

コンソールに作業中のGitブランチ名を表示させたい理由は単に見た目が格好いいから、だけではありません。

時々、今どのブランチで作業しているのだっけ?となります。また、うっかりコミットするブランチを間違えたりもします。 そんな無駄やリスクを避けるためにブランチ名が見やすい位置に表示されているととても便利なわけです。

RStudioでもGit管理しているプロジェクトのブランチ名が表示されますが、常には表示されていません。複数あるタブの中からGitタブを選択した状態でない確認できません。GUI RやターミナルでRを実行する場合はこの機能もないので、ブランチの確認は別の方法頼みとなります。なので、コードを書いたり実行するコンソールに表示させておくと常にブランチを意識でき、上記の問題を回避可能です。

設定方法

利用するにはパッケージをインストールする必要があります。CRAN未登録なため開発版をGitHubから導入します。

install.packages("remotes")
remotes::install_github("gaborcsardi/prompt")
library(prompt)

promptには

  • prompt_*() で見た目の確認
  • set_prompt()prompt_*()の内容を反映させる
  • suspend(), restore(), toggle() で元に戻す

の機能があります。

Gitブランチ名の出力の他、実行したコードのステータス、起動中のRプロセスにおけるメモリ分配量の表示が可能です。

f:id:u_ribo:20191215095220j:plain

上記の画像は prompt_fancy を指定したターミナルでのRの画面です。オシャレですねー。

では本題、Gitブランチ名の表示を反映させましょう。コンソールで次のコマンドを実行します。なおGitバージョン管理をしていないプロジェクトないし作業ディレクトリでは通常のプロンプトが表示されます。

set_prompt(value = prompt_git)

もちろんmaster以外であればそのブランチ名になります。さらにGitでバージョン管理しているファイルに変更がある状態だとブランチ名の最後に * がつきます。

最後に、この設定はRを終了するとなくなってしまうので、起動時に実行されるよう.Rprofileに書き込んでおきましょう。.Rprofileの編集はusethis::edit_r_profile()を使うのが簡単です。

私の設定は次のようになっています。

.First <- function() {
  if (interactive()) {
    prompt::set_prompt(value = prompt::prompt_git)
  }
}

おまけ: 視認性の高いhackフォントへの変更

Hadleyが登壇している動画を見ていると、彼のRStudio画面で使われているフォントに目が行きます。探してみると、Hadleyは2015年からこのフォントを使っているみたいです(今更気づいてしまった)。

Hack、名前がいいですね。こちらもサクッと真似しましょう。

github.com

f:id:u_ribo:20191215095240p:plain

Hackに設定したRStudioのキャプチャ画面です。0とO、lと1など、見分けづらい文字の視認性が上がっているように思います。

RStudioではエディタやコンソールで表示されるフォントを好みのものに変更できるので、ぜひ気に入ったものを使ってください。 フォントをダウンロード・インストールしたら環境設定を開き、AppearanceのEditor Fontに指定するだけです。 良さげなフォントについては https://blog.nakanishy.com/programming-fonts.html が参考となりました。

ちなみに、これまでは合字に対応したFireCodeInconsolataを使っていました。

Enjoy!


  1. システムが入力を待っている状態の時に表示される文字や記号です。Rではデフォルトで > がプロンプトとして使われます。