cucumber flesh

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

標準的な公共交通機関の情報形式 GTFS をRで処理する: gtfsrouter編

f:id:u_ribo:20191117103306j:plain

この記事はRアドベントカレンダー2019の5日目の投稿です。昨日は id:ando_Roid さんの投稿でした。

はじめに

今回で4回目となる「東京公共交通オープンデータチャレンジ」の応募が始まりました。これは公共交通オープンデータやその他のオープンデータを活用したアプリケーションおよびサービスの提案に関するコンテストです。ここでは、鉄道、バス、航空などの交通機関のデータが、GTFS (General Transit Feed Specification) 形式で公開されています。

GTFSは公共交通機関の時刻表と地理的情報に関するオープンフォーマットとして定義されます。リアルタイムの運行情報を反映した動的データ (GTFS Realtime)と、ダイヤ改正等の事情がない限り安定した静的データがあり、GTFSといえば厳密には静的データの方を指します。複数の事業者・交通機関が共通の形式に従ってデータを整備することで、経路探索や時刻表のアプリケーション開発が容易になるのが利点です。そのため、GTFSを提案したGoogle以外でも広く使われています。日本の交通機関に関しても、GTFSをベースに日本独自の交通事情を加味しながら拡張されたフォーマット (GTFS-JP) が整備されています。

さて、今回はそんなGTFSをRで扱ってみようという記事になります。日本語の内容として id:nonki1974 さんがgtfsrパッケージの利用方法を スライドにまとめています。なのでここでは、もう一つの例として gtfsrouterパッケージを紹介します。

目次です。

  • はじめに
  • gtfsrouterパッケージ
    • デモデータの処理
    • data.tableによるGTFSデータの操作
  • RでGTFSデータを扱う際のTips
    • 連続値になっている時刻の変換
    • sfオブジェクトへの変換

gtfsrouterパッケージ

github.com

gtfsrouterパッケージの特徴として次の点が挙げられます。

  • 2019年12月5日現在、CRANに登録されている。gtfsrは未登録
    • ただし、現在はGitHub上の開発版を利用するのが良さそう (issue #14 参照)
  • GTFSデータをdata.tableオブジェクトとして処理するため、処理速度の高速化が期待できる
  • 指定時間内に移動可能な領域 (Isochrone map) の描画ができる

まずはパッケージを利用可能な状態にしておきます。CRANに登録されているバージョンではなくGitHub上の開発版をインストールします。

install.packages("remotes")
remotes::install_github("ATFutures/gtfs-router")
# gtfs_isochrone()を実行する際に必要です
# install.packages(c("alphahull", "geodist"))
続きを読む

住所や年号、漢数字のデータ操作を楽にするRパッケージをCRANに登録しました

副題「失われた『Nippon』を求めて」(仰々しい)。

f:id:u_ribo:20191202115448j:plain
Kajikazawa in Kai Province (Koshu Kajikazawa), from the series “Thirty-six Views of Mount Fuji (Fugaku sanjurokkei)”, 1825–1838 by Katsushika Hokusai. Image via Art Institute of Chicago

NipponパッケージというRパッケージがあります。 このパッケージは、日本人が頻繁に遭遇するであろう、全角英数字や元号の変換、祝日の判定といった処理を効率的に行うための関数や日本の都道府県名を含んだデータセットを提供していました。

いました、と過去形にするのは今年(2019年)の7月にCRANからアーカイブされてしまったためです。現在は install.packages("Nippon") を実行してもインストールできません。

Nipponパッケージは当然日本人の利用者も数多く、日本人Rユーザが集うSlack、r-wakalang上でも「なぜアーカイブされたのか」「今後はどうなるのか」というやり取りもありました。 パッケージがCRANから除外されてしまった経緯はさておき、このパッケージの関数は私自身も重宝していたのでなんとかしたいという気持ちでいました。 そして今回、Nipponパッケージの代替え、そしてより便利な機能を提供することを目指して、新たにzipanguという名前のパッケージをCRANに登録しました。

cran.rstudio.com

とりあえずCRANからインストールできる状態を目標にしていたため、まだ使える機能は限定的ですが各関数の使い方を解説します。 まずはパッケージを利用するために、パッケージのインストールを行います。

install.packages("zipangu") # v.0.1.0
library(zipangu)

zipanguパッケージの関数

Address: 住所文字列の要素分割

与えられた住所文字列をその要素、すなわち都道府県、市区町村、それ以下の住所に分割、リストとして返却します。

separate_address("東京都千代田区大手町一丁目")
#> $prefecture
#> [1] "東京都"
#> 
#> $city
#> [1] "千代田区"
#> 
#> $street
#> [1] "大手町一丁目"
separate_address("北海道余市郡余市町朝日町")
#> $prefecture
#> [1] "北海道"
#> 
#> $city
#> [1] "余市郡余市町"
#> 
#> $street
#> [1] "朝日町"
separate_address("宮城県柴田郡村田町大字村田")
#> $prefecture
#> [1] "宮城県"
#> 
#> $city
#> [1] "柴田郡村田町"
#> 
#> $street
#> [1] "大字村田"

住所の一部が与えられた時は、欠損する要素をNAとして処理します。

separate_address("岡山市")
#> $prefecture
#> [1] NA
#> 
#> $city
#> [1] "岡山市"
#> 
#> $street
#> [1] NA
separate_address("奈良県高市郡高取町")
#> $prefecture
#> [1] "奈良県"
#> 
#> $city
#> [1] "高市郡高取町"
#> 
#> $street
#> [1] NA

ソースコードを見たらわかるのですが、力づくでの正規表現によるパターンマッチで実装しているのでもっとスマートに書ける気がしています。

Year: 元号が使われる年表記を西暦に変換

convert_jyear()関数で「平成元年」や「昭和52年」、「T5」(大正5年)といった元号を用いた年表記を西暦での表記に変換します。Nipponパッケージが対応していなかった「令和」にも対応しています。

convert_jyear("平成元年")
#> [1] 1989
convert_jyear(c("R1", "昭和52年"))
#> [1] 2019 1977

この処理の逆、西暦から元号へは対応していません。次のバージョンでの課題です。

Kansuji: 漢数字をアラビア数字に変換

デフォルトでは変換したアラビア数字は文字列型として処理されますが、数値として返却させるなど、いくつかのオプションがあります。

kansuji2arabic(c("一", "百"))
#> [1] "1"   "100"
# 返り値を数値にします
kansuji2arabic(c("一", "百"), convert = FALSE)
#> [1]   1 100
# .under = で指定した値未満の漢数字だけを対象とします
kansuji2arabic(c("一", "百", "千"), .under = 1000)
#> [1] "1"   "100" "千"

住所のように、文字列中のすべての漢数字をアラビア数字に変えるには kansuji2arabic_all()が利用できます。

kansuji2arabic_all("北海道札幌市中央区北一条西二丁目")
#> [1] "北海道札幌市中央区北1条西2丁目"

str_jconv: 全角・半角、ユニコード正規化

この関数はCRAN登録のv0.1.0では利用できません。

Nipponパッケージではzen2han()han2zen()kata2hira()hira2kata()といった関数で全角文字列を半角にしたり、片仮名と平仮名の変換を行える関数がありました。 zipanguでも以下の関数を用意する予定です。

str_conv_hirakana("アイウエオ", to = "hiragana")
#> [1] "あいうえお"
str_conv_hirakana("あいうえお", to = "katakana")
#> [1] "アイウエオ"
str_conv_zenhan("a0", "hankaku")
#> [1] "a0"
str_conv_zenhan("ガッ", "zenkaku")
#> [1] "ガッ"

また、Nipponにはなかったユニコード正規化のための関数も実装予定です。

str_conv_normalize("①②③", "nfkc")
#> [1] "123"

祝日の判定

この関数はzipangu v0.1.0では未実装です。 Nippon::is.jholiday()として提供されていたものです。日付オブジェクトを与えると、その日が祝日かどうかを返却する関数です。

Nippon::is.jholiday(as.Date("2019-11-03"))
#> [1] TRUE
# 天皇誕生日の変更についてはサポートされていない
Nippon::is.jholiday(as.Date("2019-12-23"))
#> [1] TRUE

祝日のリストから対応する日付を判定させれば良いのですが、今年のようにイレギュラーな祝日が入ったりすることまでサポートしようとすると実装は大変そうです。

Nipponパッケージを使いたい

まだ未実装の関数もあり、アーカイブされたとはいえNipponパッケージを使いたい方は、下記のコードを実行することでNipponパッケージが利用可能になります。

remotes::install_github("cran/Nippon")

開発に協力してください

最後にお願いです。

NipponパッケージのソースコードGitHub等で公開されてはいませんでした。 機能改善やバグ報告は受け付けていましたが、メールでのやり取りに敷居の高さを感じていた方もいたのではないでしょうか。

zipanguパッケージは多くのRパッケージ同様、オープンソースで開発、ソースコードGitHub上で公開しています。 問題の報告や改善点の要望もGitHubのissueで受け付けています。 これらは誰でもできるので、今更言うほどでもないのですが、このパッケージの開発ならびに保守を手伝ってくれる方を募集しています。

これは私自身が、いつまでこのパッケージをメンテナンスし続けられるのかわからないためであります。 コラボレータがいることで、このパッケージがNipponと同じ轍を踏むリスクを低下させられるのではと考えています。

github.com

コラボレータを募る背景には、日本人のRパッケージ開発者を養成したいと言う気持ちがあるのですが、これについては別の記事を書くつもりです。

日本語データの処理でよく使う機能がある方はぜひお願いします。 Rのパッケージ開発についてはわからない...そんな場合でも、パッケージの作成方法についていくらか教えることができますので、遠慮なく手を挙げていただければ幸いです。

まだ小さなパッケージですが、どうぞよろしくお願いします。

Fukuoka.R#15でtidymodelsについての発表を行いました

先週末(2019年8月31日)に開催されたFukuoka.R#15 へ参加・発表してきました。Fukuoka.Rはその名の通り、九州・博多を中心として活動するRコミュニティです。私は茨城県つくば市に住んでいるので、会場のLINE Fukuokaまでは直線距離でおよそ928km離れた場所からの参加というわけです。いやはや遠い。遠いですが、参加してよかったと思える会でした。

以下、簡単にですが内容の振り返りと当日の発表では言えなかったことを書きます。

発表内容

tidymodelsによるモデル構築と運用」という題での発表です。

speakerdeck.com

tidymodelsに含まれるパッケージについて言及した日本語を記事をしばしば見かけるようになりました。私自身もいくつか記事を書いています。

blog.hoxo-m.com

blog.hoxo-m.com

しかしtidymodelsの全容、包括的な話題を扱っている日本語の情報は限られています。そこで今回は、モデルの構築から運用に至るまでの手順をパッケージの利用方法とともに紹介する形式としました。具体的には{rsample}で対象データの分割、リサンプリング、{recipes}でデータ前処理、特徴量の用意、{parsnip}でのモデル実行、最後に{yardstick}による性能評価です。

スライド資料なので、言葉足らずな面があるかと思います。 テキストと合わせた内容は id:dropout009 さんの記事 (その1,その2)を読んでおけばOKかなと感じる部分もあります。資料作成時も大変参考となりました。

今回は30分の枠でした。Tokyo.Rでは20分の枠が一般的なのでちょっと長めですね。たっぷりと話すことができました(その分詰め込みすぎて余裕がなくなってしまったという本末転倒な反省も)。tidymodelsはパイプフレンドリーで関数や操作性に一貫性があり、またパッケージがタスクに応じて分割されているので紹介もしやすかったです。

発表から除外したもの

最後の方は説明が複雑になる、時間も足りないということもあり、駆け足で説明不足になってしまいました。また、運用をタイトルに入れていたので{drake}{butcher}の紹介をと考えていましたが明らかに時間が足りない、それよりは他の説明に時間を割こうとして除外しました。そのため、こちらで簡単に補足させていただきます。

{drake}はtidymodelsの支配下にないパッケージであり、モデルとは関係しません。しかしモデル構築の作業をワークフロー化することで、再現性を確保、手間を減らすことが期待できます。おすすめです。

blog.hoxo-m.com

また当初、{butcher}を組みこもうとしていましたが結局除外してしまいました。このパッケージはモデルオブジェクトのサイズを減少させるのに効果的です。というのもモデル構築の過程でオブジェクトサイズが増大することがあるためです。関数の環境内で余分なオブジェクトを生成しているとそれが影響する感じでしょうか(よくわかっていない部分があります…)。{butcher}パッケージの名前は肉屋の従業員。その名の通り、余分なデータを捌きます。{butcher}を利用すると先のオブジェクトサイズが減少します。やや物騒な名前の関数を使います。こちらは{parsnip}が対応するエンジンについて対応しており、すでにCRANに登録されています。

今回のテーマはtidymodelsでしたが、今Rで機械学習モデルを実行するには他の選択肢がいくつかあります。この比較についても発表時は行えませんでした。以前tweetで発信した情報がありますのでこちらをご覧ください。

また会いましょう!