Skip to contents

この記事では、jpplantnames が小さな R パッケージとしてどのように構成されているかを 説明します。公開データを、再現可能な解析用の道具に変える例として読むことを 想定しています。

English version: Building jpplantnames as an R package

小さな課題から始める

最初の目標は単純です。

scientific_name("コナラ")
#> [1] "Quercus serrata"

この短い API の裏側には、いくつかの設計判断があります。

  • 「維管束植物和名チェックリスト ver. 1.10」の非公式 wrapper として作る。
  • チェックリストデータはパッケージに同梱しない。
  • チェックリスト Excel ファイルは、必要になったときだけ取得する。
  • 2 回目以降の検索ではローカルキャッシュを使う。
  • 完全一致を基本にし、曖昧な候補を自動で選ばない。
  • 国際的な学名確認は任意機能としてチェックリスト検索から分ける。

小さな関数群ですが、データ取得、文字コード、キャッシュ、テスト、 ドキュメント、GitHub Actions まで含むため、R パッケージ作成の教材として 扱いやすい題材です。

パッケージの骨格

jpplantnames は、多くの R パッケージで使われる標準的な構成を使っています。

パス このパッケージでの役割
DESCRIPTION パッケージ情報、依存関係、URL、vignette 設定。
NAMESPACE ユーザーに公開する関数。
R/ キャッシュ、読み込み、検索、GBIF 補助関数の実装。
man/ roxygen コメントから作られる関数リファレンス。
tests/testthat/ 単体テストと小さな合成チェックリスト fixture。
vignettes/ 使い方ガイドやメンテナンスガイドなどの記事。
_pkgdown.yml ドキュメントサイトのナビゲーションと reference 分類。
.github/workflows/ R package check と pkgdown deploy の GitHub Actions。

小さなパッケージでは、この構成で十分です。重要なのは、コードは R/、 テストは tests/、長めの説明は vignettes/、自動化は .github/ というように、 役割を分けておくことです。

先に公開 API を決める

中心になる使い方は次の形です。

library(jpplantnames)

scientific_name("コナラ")
scientific_name("コナラ", with_author = TRUE)
japanese_name_search("コナラ")

その周辺に、役割のはっきりした関数を置いています。

関数 役割
japanese_name_download() チェックリスト Excel ファイルをユーザーキャッシュへ保存する。
japanese_name_load() キャッシュ済みファイルを data.frame として読み込む。
scientific_name() 和名の完全一致から標準学名を返す。
japanese_name_search() 候補行を返し、人間が確認できるようにする。
gbif_match() 学名を GBIF と照合する任意の補助関数。

この分け方にすると、簡単な用途は scientific_name() だけで済み、必要な人は 元データや候補行も確認できます。

チェックリストデータをパッケージに同梱しない

jpplantnames はチェックリストデータをパッケージ内に入れていません。データの流れは 次の通りです。

  1. scientific_name()japanese_name_search()japanese_name_load() がチェックリストデータを必要とする。
  2. キャッシュがなければ japanese_name_download() がチェックリスト Excel ファイルを取得する。
  3. ファイルをユーザーの R キャッシュディレクトリに保存する。
  4. 以後の検索ではチェックリスト配布元ではなくローカルファイルを読む。

この設計には 2 つの意味があります。まず、パッケージコードを MIT ライセンスで 公開しても、チェックリストデータそのものを再配布しません。次に、解析で何度検索しても、 検索のたびに配布元サーバーへ問い合わせることがありません。

明示的に更新したい場合だけ、次のようにします。

japanese_name_download(overwrite = TRUE)
japanese_name_load(refresh = TRUE)

チェックリスト Excel を明示的に読む

チェックリストは readxlJN_dataset シートを読み込んでいます。

readxl::read_excel(
  path = path,
  sheet = "JN_dataset",
  col_types = "text"
)

これは重要な実装ポイントです。チェックリストの列を、パッケージ内部で使う 和名別名学名学名 withAuthor などの安定した列へ正規化します。

ソースコード中の列名は、環境をまたいで編集しやすくするため、必要に応じて Unicode escape で保持しています。

検索は保守的にする

scientific_name() は fuzzy search ではなく、解析で安定して使うための関数です。 現在の仕様は意図的に狭くしています。

  • チェックリストの 和名 列と 別名 列を完全一致で検索する。
  • ステータス == "標準" の行だけを使う。
  • 標準の完全一致がない場合は NA_character_ を返す。
  • 標準の完全一致が複数ある場合はエラーにする。

これにより、疑わしい候補をスクリプトが静かに採用することを避けます。 曖昧な場合は japanese_name_search() で候補を確認します。

テストでは小さな fixture を使う

単体テストでは、チェックリスト本体の大きなファイルを毎回ダウンロードしません。 代わりに、挙動確認に必要な最小限の行だけを含む合成 fixture を使います。

この fixture で確認している主な点は次の通りです。

  • Excel シートを読めること。
  • common name と another name の検索を確認できること。
  • 見つからない場合に NA_character_ を返すこと。
  • 複数候補がある場合にエラーになること。
  • キャッシュの再利用と更新が動くこと。

GBIF やチェックリストへの live test は任意にします。外部 API の確認は smoke test としては 有用ですが、通常のローカルテストや pull request のたびに必須にすると不安定に なりやすいためです。

pkgdown でドキュメントサイトを作る

ドキュメントサイトは pkgdown で作ります。

  • README.md は英語トップページになる。
  • README.ja.md は日本語の入口になる。
  • vignettes/*.Rmd は article ページになる。
  • _pkgdown.yml でナビゲーションと reference 分類を決める。

GitHub Actions で pkgdown を実行し、生成されたサイトを GitHub Pages に公開します。 これにより、コードとドキュメントを同じリポジトリで管理でき、push ごとに 再現可能な形で公開できます。

今後の拡張案

次の機能を足す場合も、保守的な既定動作を保つのが安全です。

  • ひらがな・カタカナ変換や全角・半角の正規化を明示的に追加する。
  • japanese_name_search() に候補ランキングを追加する。
  • WFO や Catalogue of Life などの任意チェック関数を追加する。
  • 監査用にチェックリストの追加メタデータを返せるようにする。
  • scientific_name() の結果をデータフレームに結合する実例記事を追加する。

探索的な機能は japanese_name_search() や補助関数に寄せ、scientific_name() はスクリプトで 予測しやすい挙動のままにしておくのが基本方針です。

次に読むもの