--- title: "R2camtrapdp: スキーマ駆動ワークフロー(日本語)" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{R2camtrapdp schema-driven workflow (Japanese)} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) ``` ```{r setup} library(R2camtrapdp) ``` # 概要 `R2camtrapdp` は、任意のスプレッドシート形式で保持したカメラトラップデータを [Camera Trap Data Package (Camtrap DP)](https://camtrap-dp.tdwg.org/) へ変換します。 本バージョンは **スキーマ駆動** です。出力テーブルの構造・型・制約は、指定した Camtrap DP バージョンの公式 Frictionless *table schema* から読み取られます。 その結果、本パッケージは * **任意の Camtrap DP バージョン**(`1.0`, `1.0.1`, `1.0.2`)に対応し、さらに bioacoustics 拡張のような**別のスキーマフレーバー**にも、正しいスキーマを指す だけで対応します(§8)。 * スキーマが定義する**独自列・追加列**を理解します。 * すべての値をスキーマの制約(`required`, `unique`, `enum`, `minimum`/`maximum`, `pattern`, 日付・日時の **format** ほか)に照らして検査します。 * テーブル間の**リレーション**(主キー・外部キー)を検査します。 * スキーマ内の**URL で指定された参照**(意味マッピングや description 内リンク)を すべて可視化し、見落としを防ぎます(§1)。 * Python の **Frictionless** バリデータを実行し、エラーを R 側へ返します。 旧来のヘルパ関数(`create_deployments()`, `create_media()`, `create_observations()`)と `R6_CamtrapDP` クラスは名前・引数とも従来どおりで、 既存スクリプトはそのまま動作します。スキーマ駆動の挙動はその上に追加されています。 > **ネットワークについて。** テーブルを登録する(`set_deployments()` 等)と、 > 指定バージョンの table schema を初回に GitHub から取得し、以後はキャッシュします。 > オフライン環境では `local_schema =` 引数でローカルのスキーマファイルを渡せます。 # データ 本パッケージには、画像記録を伴う複数デプロイメントの例データが同梱されています。 ```{r} # 複数デプロイメント・画像データ data("Idep") # デプロイメント表 data("Iobs") # 観察表 ``` `Idep` はデプロイメント(カメラ設置)1 件につき 1 行で、`deploymentID`, `longitude`, `latitude`, `locationID`, `startDate`/`startTime`, `endDate`/`endTime`, `cameraID`, `cameraModel`, `Delay`, `Height`, `bait`, `setupBy` などの列を持ちます。`Iobs` は観察 1 件につき 1 行で、機関/コレクション コード、`filename`, `deploymentID`, `date`/`time`, `obsID`, `eventID`, `eventStart`/`eventEnd`, `object`, `genus`, `species`, `class`, `individualCount` を持ちます。 # 1. バージョンの選択とスキーマの確認(任意) パイプライン全体は選択したバージョンのスキーマで駆動されます。Camtrap DP の `1.0` / `1.0.1` / `1.0.2` はすべて対応しており、これらの table schema は列名・型・ 制約が共通であるため、実質的な差は `1.0.2` が欠損値トークン(`NA`, `NaN`, `nan`) を追加で認識する点のみです。任意バージョンのスキーマは `TableSchema` で直接確認 できます。 (注: 公式の `1.0` *profile*(メタデータの JSON Schema)には上流のバグ(不正な内部 `$ref`)があり、新しい Frictionless が拒否します。このため `version = "1.0"` を指定 すると警告が表示されます。`validate_frictionless()` が自動で回避しますが、`1.0.1` 以降の利用を推奨します。) ```{r, eval = FALSE} version <- "1.0.1" dep_schema <- TableSchema$new("deployments", version = version) dep_schema$field_names() # スキーマが定義する全列 dep_schema$required_field_names() # 必須(存在かつ非欠損)の列 dep_schema$empty_table() # 型付き 0 行の「殻」テーブル ``` 通常は手作業で確認する必要はありません(`R6_CamtrapDP` が適切なスキーマを自動取得・ キャッシュします)が、当該バージョンが何を要求するかの把握に役立ちます。 `check_schema()` は、スキーマ自体が well-formed な Frictionless Table Schema か (サポートされる `type`、型ごとに妥当な制約、定義済みフィールドを指す主キー・外部 キー)を確認します。新規・手編集のスキーマを採用する前の点検に有用です。 ```{r, eval = FALSE} dep_schema$check_schema() ``` ## スキーマ内の外部(URL)参照 Camtrap DP の情報の一部は、機械検証可能な制約ではなく **URL** で指定されます。 具体的には意味マッピング(`skos:exactMatch` / `broadMatch` / `narrowMatch` による Darwin Core, Audubon Core 等の用語への対応)や、フィールドの description 内の参照 URL(例: `fileMediatype` の IANA メディアタイプ登録簿、`individualSpeed` の手法 DOI) です。本パッケージが強制するのは構造化された制約のみで、**URL で参照される意味は 検証されません**。バージョンや新フレーバーを採用する際にこうした指定を見落とさない よう、次で一覧化できます。 ```{r, eval = FALSE} dep_schema$external_references() # スキーマが宣言する全 URL(skos・description・schema URL) dep_schema$semantic_only_fields() # 意味が URL でのみ定義され、値域を機械検証できない列 ``` `external_references()` は整形済みの表(`resource`, `field`, `key`, `category`, `url`)を返します。`semantic_only_fields()` は、参照先の権威に照らして手動確認が 必要な列を示します。パッケージ全体は `datapackage$external_references()` で一括 スキャンできます。 # 2. 3 つの中核テーブルの作成 ## デプロイメントの作成 デプロイメントデータ(`Idep`)を用い、従来どおりに作成します。 `create_deployments()` は結合済みの日時、または日付列・時刻列の別指定の両方を 受け付けます。 ```{r} deployments <- create_deployments( deploymentID = Idep$deploymentID, longitude = Idep$longitude, latitude = Idep$latitude, locationID = Idep$locationID, deploymentStart_date = Idep$startDate, deploymentStart_time = Idep$startTime, deploymentEnd_date = Idep$endDate, deploymentEnd_time = Idep$endTime, cameraID = Idep$cameraID, cameraModel = Idep$cameraModel, cameraDelay = Idep$Delay, cameraHeight = Idep$Height, baitUse = Idep$bait, setupBy = Idep$setupBy) ``` `create_deployments()` は上記以外に次の引数も受け付けます: `deploymentStart` / `deploymentEnd`(結合済み日時。`*_date` / `*_time` の組の代わりに使用)、 `locationName`、`coordinateUncertainty`、`cameraDepth`(`cameraHeight` と同時指定 不可)、`cameraTilt`、`cameraHeading`、`detectionDistance`、`timestampIssues`、 `featureType`、`habitat`、`deploymentGroups`、`deploymentTags`、 `deploymentComments`、`tz`(タイムゾーン、既定 `"Asia/Tokyo"`)。 ## メディアの作成 ```{r} # メディア ID mediaIDi <- paste(Iobs$institutionCode, Iobs$collectionCode, Iobs$locationID, as.numeric(factor(Iobs$filename)), sep = "_") # ファイル情報 fileName <- Iobs$filename filetype <- tolower(unlist(lapply(strsplit(fileName, "\\."), "[", 2))) fileMediatype <- paste("image", filetype, sep = "/") filePublic <- !grepl("ヒト", fileName) # ヒト画像は非公開にする media <- create_media( mediaID = mediaIDi, deploymentID = Iobs$deploymentID, timestamp_date = Iobs$date, timestamp_time = Iobs$time, filePath = "Image", filePublic = filePublic, fileMediatype = fileMediatype, captureMethod = "activityDetection", fileName = fileName) ``` `create_media()` は上記以外に次の引数も受け付けます: `timestamp`(結合済み日時。 `timestamp_date` / `timestamp_time` の代わり)、`exifData`、`favorite`、 `mediaComments`、`tz`、`omitduplicate`(重複 `mediaID` を除外。既定 `TRUE`)。 ## observationの作成 ```{r} # イベント単位の観察 observationLevel <- "event" # observationType はスキーマの enum 値のいずれか observationType <- ifelse(Iobs$object == "hito", "human", ifelse(Iobs$object == "none", "blank", ifelse(Iobs$object == "unidentifiable", "unknown", "animal"))) # 学名 scientificName <- ifelse(is.na(Iobs$genus), Iobs$class, paste(Iobs$genus, Iobs$species)) # 一意の観察 ID observationID <- paste(mediaIDi, Iobs$obsID, sep = "_") observations <- create_observations( observationID = observationID, deploymentID = Iobs$deploymentID, eventID = Iobs$eventID, eventStart = Iobs$eventStart, eventEnd = Iobs$eventEnd, observationLevel = observationLevel, observationType = observationType, scientificName = scientificName, count = Iobs$individualCount, classificationMethod = "human", classificationProbability = 1) ``` `create_observations()` は上記以外に次の引数も受け付けます: `mediaID`、 `eventStart_date` / `eventStart_time` と `eventEnd_date` / `eventEnd_time` の組 (結合済み `eventStart` / `eventEnd` の代わり)、`cameraSetupType`、`lifeStage`、 `sex`、`behavior`、`individualID`、`individualPositionRadius`、 `individualPositionAngle`、`individualSpeed`、`bboxX`、`bboxY`、`bboxWidth`、 `bboxHeight`、`classifiedBy`、`classificationTimestamp`、`observationTags`、 `observationComments`、`tz`、`omitduplicate`。 # 3. データパッケージの組み立て ## R6 オブジェクトの作成(バージョン指定) ```{r} datapackage <- R6_CamtrapDP$new(version = "1.0.1") ``` ここで与える `version` が、検証および `datapackage.json` に使われるスキーマを 選択します。別の Camtrap DP リリースを対象にする場合は変更してください。 ## テーブルの登録(スキーマ検証付き) `set_deployments()`, `set_media()`, `set_observations()` は名前を維持しつつ、 各々が**スキーマ型への変換と、選択バージョンのスキーマに対する検証**を行います。 問題は要約として表示され、`validate = FALSE` で表示を抑制できます。 ```{r, eval = FALSE} datapackage$set_deployments(deployments) datapackage$set_media(media) datapackage$set_observations(observations) ``` *(スキーマの取得、ファイル書き出し、分類検索、Python 呼び出しを伴うチャンクは、 本 vignette のビルド時には表示のみで実行されません。そのため出力は表示されません。)* 検証の要約は、各問題について、ファイル・列・行・違反した規則・メッセージを示します。 例えば `enum` に反する値、`minimum`/`maximum` の範囲外の数値、必要な書式に一致しない 日時などです。列の型にすら適合しない値(例: `number` 列の非数値文字列)は、無言で `NA` に変換されるのではなく `type` エラーとして報告されます。 ## テーブル間リレーションの検査 外部キー(例: `media.deploymentID` は `deployments` に、`observations.mediaID` は `media` に存在する必要がある)と主キーの一意性は、各テーブルのスキーマから読み取られ、 登録済みのテーブル間で検査されます。 ```{r, eval = FALSE} datapackage$check_relations() ``` 主キーまたは必須の外部キー列が、格納後のテーブルで**まるごと欠損**している場合 (多くは列名不一致で型変換が `NA` 補完したケース)、`check_relations()` は警告を出し データを指し示します(例: `datapackage$data$observations has 'deploymentID' entirely missing ...`)。 `datapackage$data$` を直接確認できます。 # 4. メタデータ Camtrap DP は 5 つの必須メタデータ(contributors, project, spatial, temporal, taxonomic)と `created` を必要とします。さらに 6 つの任意プロパティがあります。 メタデータ関数は従来版から変更ありません。 ## どのメタデータが必須かを profile で確認する 必須メタデータ自体は、パッケージ **profile**(JSON Schema)から読み取られます。 `metadata_requirements()` は必須トップレベルプロパティ・それを設定するメソッド・ 現在の設定状況を一覧化し、`check_metadata()` は現在のオブジェクトを profile に 照合して不足(`project.samplingDesign` のようなネストしたキーを含む)を報告します。 ```{r, eval = FALSE} datapackage$metadata_requirements() # チェックリスト: property, required, set_with, currently_set datapackage$check_metadata() # 不足している必須メタデータを報告 ``` これは Frictionless が行うメタデータ(profile)検証(§6)に相当する R 側の事前 チェックで、パッケージを書き出して Python を呼ぶ**前に**必須構造を確認できます。 ## 必須メタデータ ### 貢献者(Contributors) `add_contributors()` は `title`, `email`, `path`, `role`, `organization` 列を持つ データフレームを取り込みます。`role` は `contact`, `principalInvestigator`, `rightsHolder`, `publisher`, `contributor` のいずれかです。 ```{r} cd <- data.frame( title = c("Keita Fukasawa", "Kana Terayama"), email = c("fukasawa@nies.go.jp", "terayama.kana@nies.go.jp"), path = c("https://orcid.org/0000-0003-0272-9180", "https://orcid.org/0000-0001-6935-7233"), role = c("contact", "principalInvestigator"), organization = c("National Institute for Environmental Studies (NIES)", "National Institute for Environmental Studies (NIES)")) datapackage$add_contributors(cd) ``` ### プロジェクト(Project) ```{r} datapackage$set_project( title = "DummyData", samplingDesign = "simpleRandom", captureMethod = "activityDetection", individualAnimals = FALSE, observationLevel = "event") ``` `samplingDesign` は `simpleRandom`, `systematicRandom`, `clusteredRandom`, `experimental`, `targeted`, `opportunistic` のいずれか、`captureMethod` は `activityDetection` または `timeLapse`、`observationLevel` は `media` または `event` です。任意で `id`, `acronym`, `description`, `path` も指定できます。 ### 空間・時間(Spatial and temporal) `set_st()` はデプロイメントから空間・時間範囲を導出するため、 `set_deployments()` の後に呼び出します。 ```{r, eval = FALSE} datapackage$set_st() ``` ### 分類(Taxonomic) `set_taxon()` は観察の一意な `scientificName` を列挙し、`taxonID`, `taxonRank` と 上位分類を分類データベース(既定は `gbif`。`itis` / `ncbi` も可。`taxadb::get_ids` 参照)から取得します。CamtrapDP の `taxonomic` には `taxonID`(GBIF/IUCN 等の識別子・ URI)が必要なため、`taxadb` は R2camtrapdp の**必須依存**(パッケージと共に導入)です。 本処理にはインターネット接続も必要です。 ```{r, eval = FALSE} datapackage$set_taxon() ``` マッチできない名前は `taxonID = NA`(出力では省略。`NA` のような不正値にはなりません)。 `set_taxon()` は、`scientificName` に不要な空白がある場合と、選択した DB に `taxonID` が 無い場合に**警告**を出すので、対象の名前を修正・確認できます。 ### 作成日時(Created) ```{r} datapackage$update_created(tz = "Asia/Tokyo") ``` ## 任意メタデータ ### ライセンス(Licenses) Camtrap DP はデータ用とメディア用に各 1 つ以上のライセンスを想定します。 ```{r} datapackage$add_license(name = "CC-BY-4.0", path = "http://creativecommons.org/licenses/by/4.0/", scope = "data") datapackage$add_license(name = "CC-BY-4.0", path = "http://creativecommons.org/licenses/by/4.0/", scope = "media") ``` ### 関連識別子(Related identifiers) ```{r} datapackage$add_relatedIdentifiers( relationType = "IsSupplementTo", relatedIdentifier = "https://doi.org/xxxx", relatedIdentifierType = "DOI", resourceTypeGeneral = "JournalArticle") ``` ### プロパティ・ソース・参考文献 ```{r} datapackage$set_properties( name = "dummy-nies", homepage = "https://www.nies.go.jp/biology/snapshot_japan/index.html") datapackage$add_sources(title = "DummyData") datapackage$add_references(reference = "DummyNIES https://doi.org/xxxxx") ``` ### カスタムリソース `set_custom()` は追加のリソース(例: 個体数推定に使うデータ)をメタデータとして 付加します。3 つの中核テーブルを登録した後に呼び出します。 ```{r} RD <- data.frame(id = seq_len(388), Time = sample(1:29, 388, replace = TRUE)) ``` ```{r, eval = FALSE} datapackage$set_custom(name = "rest", description = "data for the REST method", data = RD) ``` # 5. データパッケージの出力 ```{r, eval = FALSE} # camtrapdp オブジェクトを返す data_camtrapdp <- datapackage$out_camtrapdp() # あるいは deployments.csv / media.csv / observations.csv + datapackage.json を書き出す datapackage$out_camtrapdp(write = TRUE, directory = path) ``` 書き出し時、CSV は全スキーマ列を含み、boolean は `true`/`false`(小文字)で出力され、 未設定のメタデータは省略されるため、空のプレースホルダが偽の検証エラーを引き起こす ことはありません。 # 6. Frictionless による検証 ## 適合の事前チェック(Python を呼ぶ前に) Python を実行する前に、パッケージがそもそも well-formed な Frictionless データ パッケージか、また CamtrapDP 形式かを R 側で確認できます。Frictionless が行う構造 チェックを R で再現するもので、新規・特殊なスキーマの問題を早期に発見できます。 ```{r, eval = FALSE} datapackage$check_descriptor() # 記述子+各 table schema の構造(Frictionless 仕様) datapackage$check_camtrap_profile() # profile が CamtrapDP でなければ警告 ``` パッケージは **Frictionless** として妥当でも、**CamtrapDP** 形式とは限りません。 それは `profile` が CamtrapDP プロファイル(既定)かどうかで決まります。GeoJSON 妥当性や物理ファイル構造を含む権威ある判定は、下記の Frictionless 実行が担います。 ## Frictionless の実行 書き出したパッケージを公式スキーマに照らして、Python の [Frictionless](https://framework.frictionlessdata.io/docs/guides/validating-data.html) で確認できます。`frictionless` を導入した Python が必要です (`pip install frictionless`)。 ```{r, eval = FALSE} issues <- datapackage$validate_frictionless(directory = path, python = "python") ctdp_is_valid(issues) # error が無ければ TRUE ``` **注意 — `path` を上書きします。** `validate_frictionless()` は既定で `write = TRUE` のため、検証前に `out_camtrapdp()` を呼んで `directory` 内の `datapackage.json` と CSV を**現在のオブジェクトの内容で上書き**します。すでに ディスク上にある datapackage を**上書きせず検証だけ**したい場合は `write = FALSE`、 または R6 オブジェクト不要の検証専用関数を使ってください: ```{r, eval = FALSE} ctdp_validate_frictionless("path/to/existing/package", python = "python") ``` `issues` は問題 1 件につき 1 行の整形済み表で、`source`(ファイル)、`field`(列/ プロパティパス)、`row`(行)、違反した `constraint`、問題の `value`(実値)、 `message` を与えるため、エラー箇所を正確に把握できます。セルエラーの `value` は不正な セル値、メタデータ(profile)エラーの `value` は note 内のプロパティパス(例 `contributors[].email`)で `datapackage.json` を辿って解決した実値です。R 側のスキーマ検査・リレーション検査・メタデータ(profile)検査・ 適合事前チェック・(任意で)Frictionless レポートは、1 回の呼び出しで集約する こともできます。 ```{r, eval = FALSE} datapackage$validate(relations = TRUE, metadata = TRUE, conformance = TRUE, frictionless = TRUE, directory = path, python = "python") ``` # 7. 任意のスプレッドシートを直接変換する 上記のヘルパは変数を事前に命名済みであることを前提とします。独自の列名を持つ生の スプレッドシートがある場合は、`ctdp_build_table()` でマッピング・日時結合・型変換・ 検証を一括実行できます(任意バージョン対応)。 ```{r, eval = FALSE} version <- "1.0.1" dep_schema <- TableSchema$new("deployments", version = version) # 任意の列名+独自列を持つ生データの例 raw <- data.frame( station = c("A01", "A02"), lat = c(35.1, 36.2), lon = c(139.5, 140.1), start_day = c("2023-04-01", "2023-04-02"), start_clk = c("09:00:00", "10:30:00"), end_day = c("2023-05-01", "2023-05-02"), end_clk = c("09:00:00", "10:30:00"), myNote = c("独自列として保持", "これも保持"), stringsAsFactors = FALSE) # マッピング:生データで使用されている列名とCamtrapDPのフィールド名との関係(マッピング)を作成 mapping <- c(station = "deploymentID", lat = "latitude", lon = "longitude") built <- ctdp_build_table( dep_schema, raw, mapping = mapping, datetime_merges = list( list(date_col = "start_day", time_col = "start_clk", target = "deploymentStart"), list(date_col = "end_day", time_col = "end_clk", target = "deploymentEnd"))) ctdp_summarize_validation(built$issues) # スキーマ上の問題 datapackage$set_deployments(built$data) # 結果をパッケージへ投入 ``` `myNote` のような独自列は保持されます。パッケージ書き出し時、独自列は `datapackage.json` 内のインライン拡張スキーマとして宣言されるため、Frictionless が 受理します。 # 8. 別のスキーマフレーバー(例: bioacoustics) 各テーブルは指し示したスキーマで駆動されるため、本パッケージは TDWG がホストする カメラトラップのスキーマに限定されません。別フレーバー——例えば Camtrap DP の [bioacoustics 拡張](https://github.com/camera-traps/bioacoustics)——を対象にする には、テーブルおよび profile の URL を明示します。これらのスキーマは別リポジトリに あり、独自の列構成(例: `cameraID` の代わりに `deviceID`、さらに `samplingFrequency`, `frequencyLow`/`frequencyHigh` など)と、テーブルごとに異なる 日時書式(`media` / `observations` のイベント時刻は小数秒付き `%Y-%m-%dT%H:%M:%S.%f%z`、`deployments` の時刻は小数秒なし)を用います。スキーマ駆動 の検証はこれらすべてに自動的に適応します。生データの `media` / `observations` の タイムスタンプに小数秒が無い場合は、スキーマの `%f` 書式に合うよう **`.000` を自動 付与**します。 `set_properties()` でフレーバーを一度指定すれば、あとは通常どおりテーブルを追加 できます(`set_*()` は設定済みの `schema_urls` を使うため、各呼び出しに `schema =` を渡す必要はありません)。 ```{r, eval = FALSE} ba <- "https://raw.githubusercontent.com/camera-traps/bioacoustics/main/camtrap-dp/1.0.2/%s" dp <- R6_CamtrapDP$new(version = "1.0.2") dp$set_properties( version = "1.0.2", profile = sprintf(ba, "camtrap-dp-profile-acoustic.json"), schema_urls = list( deployments = sprintf(ba, "deployments-table-schema-acoustic.json"), media = sprintf(ba, "media-table-schema-acoustic.json"), observations = sprintf(ba, "observations-table-schema-acoustic.json"))) # 音響のタイムスタンプは、音響スキーマの書式に合わせて小数秒を付与する dp$set_media(data.frame( mediaID = "m1", deploymentID = "D1", timestamp = "2023-04-01T09:05:00.000+0900", filePath = "audio/m1.wav", filePublic = TRUE, fileMediatype = "audio/wav", samplingFrequency = 48000L, channels = 1L, stringsAsFactors = FALSE)) ``` ## カメラトラップの列を音響フレーバーへ対応づける マッピングが必要なのは、**名前が音響フィールドと異なる列だけ**です。すでに音響 フィールド名と同じ列(`deploymentID`, `latitude`, `deploymentStart` など)は自動的に 対応づけられ、**マッピングは不要**です。deployments では、カメラトラップの `camera*` 列が `device*` に改名され、カメラ専用列は音響に対応が無いため除外し、音響固有の列は データがあれば設定します。 ```{r, eval = FALSE} library(dplyr) # カメラトラップ deployments -> 音響 deployments(改名が必要な列だけ) mapping <- c( cameraID = "deviceID", cameraModel = "deviceModel", cameraDelay = "deviceDelay", cameraHeight = "deviceHeight", cameraDepth = "deviceDepth", cameraTilt = "deviceTilt", cameraHeading = "deviceHeading") dep_acoustic <- camtrap_deployments %>% select(-any_of(c("featureType", "timestampIssues"))) # カメラ専用: 音響に対応列なし dp$set_deployments(dep_acoustic, mapping = mapping) ``` 列の対応 — **deployments**: | カメラトラップの列 | 音響の列 | 対応 | |---|---|---| | `deploymentID`, `locationID`, `locationName`, `latitude`, `longitude`, `coordinateUncertainty`, `deploymentStart`, `deploymentEnd`, `setupBy`, `detectionDistance`, `baitUse`, `habitat`, `deploymentGroups`, `deploymentTags`, `deploymentComments` | *同名* | **マッピング不要** | | `cameraID` / `cameraModel` / `cameraDelay` / `cameraHeight` / `cameraDepth` / `cameraTilt` / `cameraHeading` | `deviceID` / `deviceModel` / `deviceDelay` / `deviceHeight` / `deviceDepth` / `deviceTilt` / `deviceHeading` | **マップ** | | `featureType`, `timestampIssues` | — | **除外** | | — | `elevation`, `devicePlatform`, `recordingSchedule`, `locationType` | 音響固有(あれば設定) | **observations** で改名が必要なのは `cameraSetupType` → `deviceSetupType` のみです (音響は `frequencyLow` / `frequencyHigh` / `classificationConfirmation` も追加)。 **media** に改名はなく、追加フィールド(`duration`, `bitDepth`, `samplingFrequency`, `gain`, `channels`)のみです。 フレーバーのスキーマも、他のスキーマと同様に確認できます。なお `TableSchema$new("deployments", version = "1.0.2")` を `url_template` **なし**で 呼ぶと*カメラトラップ*用の deployments スキーマが読み込まれます。音響の要件を確認 するには音響 URL を渡してください。`requirements()` は各フィールドの型・書式・制約を 表で返します。 ```{r, eval = FALSE} acoustic_dep <- TableSchema$new( "deployments", version = "1.0.2", url_template = sprintf(ba, "deployments-table-schema-acoustic.json")) acoustic_dep$field_names() acoustic_dep$required_field_names() acoustic_dep$requirements() # field / type / format / required / enum / min / max / pattern acoustic_dep$external_references() ``` > `create_deployments()`, `create_media()`, `create_observations()` はカメラ > トラップのスキーマに合わせて作られています。別フレーバー(または将来版の新規列) > では、`create_*()` ではなくスキーマ駆動の経路(`ctdp_build_table()` か、カスタム > `schema =` を渡した `set_*()` メソッド)でテーブルを構築してください。