気象庁のサクラ開花日のテキストファイル

 4月初旬はソメイヨシノの開花に心が躍る.古い歌にあるように,

世の中にたえてさくらのなかりせば春の心はのどけからまし

 あっという間に散っていく様は日本人の心を捉えて離さない.この桜の開花日の予測は気象庁でも行われている.

 桜だけではない.生物季節観測の情報では各種の植物,動物を観測しており,過去のデータを公表している.

 時節柄,過去の桜開花日をダウンロードして検索しやすいようにしようと考えた.

 ファイルは最初に置いておく.好きに使ってくれて構わない.

004

関連記事

テキストファイルから SQL Server に気象データをインポートする

Google FormからSQL Serverへデータを移行するには

生物季節観測値の種目

 気象庁では下表のように 57 種の生物について 65 の事象を観測している.主な植物については地方気象台の敷地内に観測用の植物を植え,標本木として観測している.

生物名 事象
あじさい 開花
あんず 開花
あんず 満開
いちょう 発芽
いちょう 黄葉
いちょう 落葉
うめ 開花
かえで 紅葉
かえで 落葉
かき 開花
からまつ 発芽
ききょう 開花
くり 開花
くわ 発芽
くわ 落葉
さくら 開花
さくら 満開
さざんか 開花
さるすべり 開花
しだれやなぎ 発芽
しば 発芽
しろつめくさ 開花
すいせん 開花
すすき 開花
すみれ 開花
たんぽぽ 開花
チューリップ 開花
つばき 開花
でいご 開花
てっぽうゆり 開花
なし 開花
のだふじ 開花
ひがんざくら 開花
ひがんざくら 満開
ひがんばな 開花
もも 開花
やまつつじ 開花
やまはぎ 開花
やまぶき 開花
ライラック 開花
りんご 開花
あきあかね 初見
あぶらぜみ 初鳴
うぐいす 初鳴
えんまこおろぎ 初鳴
かっこう 初鳴
きあげは 初見
くさぜみ 初鳴
くまぜみ 初鳴
さしば南下 初見
しおからとんぼ 初見
つくつくほうし 初鳴
つばめ 初見
とかげ 初見
とのさまがえる 初見
にいにいぜみ 初鳴
にほんあまがえる 初鳴
にほんあまがえる 初見
はるぜみ 初鳴
ひぐらし 初鳴
ひばり 初鳴
ほたる 初見
みんみんぜみ 初鳴
もず 初鳴
もんしろちょう 初見

データファイルはPDFなのだが…

 読めない.もっと言うと,マシンリーダブルでない.スペースで見栄えだけ揃えました,という感じがありありと見て取れる.テキストのないPDFファイルからテキストを抽出するにはで書いた気がするが,今どきこんな形のファイルをネット上に公開していて恥ずかしくないのか,と小一時間問い詰めたくなる.

気象庁は国民にデータを公開するとはどういうことか,分かってない

 ダウンロードした PDF を開き,メモ帳にコピペしてテキストファイルで保存.それを EXCEL で読み込もうとして,詰んだ.

テキストファイルウィザードでも対応できない

テキストファイルウィザード.スペース区切りの.txtファイルには要注意だ
テキストファイルウィザード.スペース区切りの.txtファイルには要注意だ

 .txtファイルを開く時のダイアログ.スペース区切りのテキストファイルには要注意だ.

データの区切り位置がずれる!

 もうね,呆れて何も言えない.言えないが,言わせてもらう.

データ区切りの縦線を手動で引いていく.途中で位置が合わなくなっている
データ区切りの縦線を手動で引いていく.途中で位置が合わなくなっている

こんな不揃いのデータを公開して,恥ずかしくないのか?

 せめて .csv ファイルにしてくれ.マシンリーダブルであるというのは,そういうことだ.ダウンロードしたらすぐ Excel で開いてデータベースに取り込みたいんだよ,こっちは.何なら直接データベースに突っ込みたい.

 この手の官僚仕事にはうんざりしている.

Wordで置換してみたら?

 ふと,Word の置換を使えばいいのではないかと思いついた.スペースをタブに置換してやればよい.物は試しだ.

Wordの置換.あいまい検索をオフにする.半角全角スペースというのがリストの一番下にある
Wordの置換.あいまい検索をオフにする.半角全角スペースというのがリストの一番下にある

ビンゴ!

14,000個以上のスペースがタブに置換された
14,000個以上のスペースがタブに置換された

 行けそうな気がしてきた.そのままテキストファイルで保存.Excelに戻る.

さっきよりはだいぶ良い.データの先頭が揃っている
さっきよりはだいぶ良い.データの先頭が揃っている

 マイナス記号が先頭についているデータもあるが,何とかなるだろう.

EXCELで開く.多少不揃いな箇所もある.これは手動で直すか考えどころ
EXCELで開く.多少不揃いな箇所もある.これは手動で直すか考えどころ

データの位置がまるごとずれている

 ワークシートをスクロールしていって,はたと考え込んだ.番号地点の右側,何もデータのない箇所が複数ある.

ファイルを開くとデータの位置がまるごとずれている
ファイルを開くとデータの位置がまるごとずれている

 これはどうしたものか?結論から言うと,直下の領域を丸ごとカットアンドペーストすればよかった.なんでこうなったのかよく分からないのだが.

空白行を削除

 空白行をまとめて削除する.ここらへんは機械的な作業だ.サクサク済ませる.

マイナスを削除する

 マイナスの付いたところ,どうせデータベースには入らないんだから削除しよう.置換で一括削除する.1864件.

マイナスはデータベースで言うところのNULL.不要なので一括削除
マイナスはデータベースで言うところのNULL.不要なので一括削除
1864件削除された
1864件削除された

データのズレ,手動で直すか?

 さっきマイナスの付いていたデータでセル位置がずれている.データは400件近くある.手動で直すのは大変だ.

 さて,どうする?ワークシートの一番右側に注目する.ずれている行は列の最後のデータが欠損している.ここを抽出すれば良さそうだ.

いったん,テーブルに変換

 目的は空白のセルのみにするためだ.列数は48.最後の列48にフィルターをかけて空白のみを抽出する.336行抽出された.なんだ,ほとんど全部じゃないか.

フィルターで空白セルを抽出.336行抽出された
フィルターで空白セルを抽出.336行抽出された

これは,悪手だ

 データの殆どを手動で直すなんて馬鹿げている.何か他の方法を探そう.

最初にスペースをタブに置換した時を思い出せ

 マイナスのついた数字があったな?あれが鍵だ.こういう時に正規表現で置換できるといいんだが.

もう一度,実データを見直す

迷ったら現場に立ち返る

 一晩考えた後,くだんの PDF ファイルを見直す.マイナスの後,rm 列のところが空欄になっている.メモ帳に貼り付けたデータではマイナスの直後に数値が来ている.ここにヒントがあった.

マイナスの後にスペースを付け足せばよいのでは?

 Word で.txt ファイルを開く.「ホーム」タブの「編集」から「置換」を選んでクリック.

 「検索する文字列」には半角のハイフンをキーボードから入力する.

「置換後の文字列」は「特殊文字」から「検索する文字列」を選ぶ
「置換後の文字列」は「特殊文字」から「検索する文字列」を選ぶ

 「置換後の文字列」に「特殊文字」から「検索する文字列」を選ぶ.同じ文字列で置換してどうする?と思うかも知れないが,これは正規表現エンジンにも実装されている重要な機能だ.

 さらにキーボードから半角スペースをタイプする.ダイアログはこうなる.「^&」の後に「スペース」があるのがミソだ.

「置換後の文字列」には「^& 」と入る
「置換後の文字列」には「^& 」と入る

 「全て置換」をクリック.1872件置換された.

置換結果は1872件
置換結果は1872件

スペースをタブで置換

 次はスペースをタブで置換する.「検索する文字列」に「特殊文字」から「全角または半角の空白」を選ぶ

「検索する文字列」に「特殊文字」から「全角または半角の空白」を選ぶ
「検索する文字列」に「特殊文字」から「全角または半角の空白」を選ぶ

 「置換後の文字列」は「特殊文字」から「タブ文字」を選ぶ.

「置換後の文字列」は「特殊文字」から「タブ文字」を選ぶ
「置換後の文字列」は「特殊文字」から「タブ文字」を選ぶ

 ダイアログとしてはこうなる.

「検索する文字列」「置換後の文字列」それぞれ指定した状態
「検索する文字列」「置換後の文字列」それぞれ指定した状態

 「全て置換」すると 15,133 件が置換された.

置換されたスペースは15133件
置換されたスペースは15133件

何とかデータの位置は揃ってきた.しかし…

 相変わらず地点とデータのブロックがずれているのは直っていないが,だいぶマシになってきた.EXCEL で開くと,ところどころ先頭の位置がずれている行がある.

 よく見ると,データの先頭位置が右に一個ずれている.その分,右端のセルが一個右にはみ出している.

 結論から言うと,手動でセル削除した.該当するセルを複数同時に削除しても大丈夫だ.気をつけるのは必ず「左方向にシフト」にすること.デフォルトでは「上方向にシフト」となっている.ここを間違えると取り返しがつかなくなる.

空白のセルを選んで「削除」する.必ず「左方向にシフト」にすること
空白のセルを選んで「削除」する.必ず「左方向にシフト」にすること

全体を俯瞰する

 ここで一息ついて,データ全体を俯瞰してみよう.「表示」タブから「ズーム」を選び,倍率を「25%」にする.

ワークシートを俯瞰する.倍率は25%.こうやってデータ全体の見晴らしを見てみることも時には必要
ワークシートを俯瞰する.倍率は25%.こうやってデータ全体の見晴らしを確認してみることも時には必要

 はみ出していたり,凹んだりしている箇所はないか?なさそうだ.ここまで来てやっと前処理が整った.

ページごとの行数は同じか?

 検索でページ先頭のマーカーとして残しておいた「番号」の文字を全て検索する.大事なのはセルの位置だ.差分がすべて52になっているのが見て取れる.

ページのマーカーとして残しておいた「番号」の文字列を検索.セル位置を確認
ページのマーカーとして残しておいた「番号」の文字列を検索.セル位置を確認

地点名の並び順は同じか?

 次に「地点名」の並び順が同じか確認する.試しに「稚内」を全て検索してみる.セル位置の差分は104.どうやら他の地点名も同じと見て良さそうだ.

 オリジナルの PDF は 8 ページだったが, コンパクトにまとめられそうだという見通しが立った.

カットアンドペーストで一つの塊に並べ替える

 この文書は何層にも折り畳まれた構造をしている.その折り畳まれた構造を解きほぐし,第一正規形に持っていくのが目的だ.

何層にも折り畳まれた構造.官僚ってこういう文書を作るのは得意だ
何層にも折り畳まれた構造.官僚ってこういう文書を作るのは得意だ

 とにもかくにも,地点名と年別になっているテキストの塊をカットアンドペーストでより単純な形にしていく.

カットアンドペーストでより単純な形へ
カットアンドペーストでより単純な形へ

手動とプログラムの使い分けを見極めよう

 これ以上手動で対応は無理,でもプログラムを組むには複雑すぎる.そういうボーダーラインがある.プログラムが得意なのは単純な繰り返し作業だ.

 その単純な形にまで手動で持っていけば,後はルーチン化できる.ここまで失敗を含めた試行錯誤の過程を書き記してきたのは,この国のデータに対するリテラシーを高めたいという思いからである.

 データは前処理が重要だ.前処理に手間と時間の 90 % が取られている.その時間と手間が惜しい.この記事を読んだ人は,官僚の作るデータがいかに使いにくいか,よく分かっていると思う.

 すぐに使える形でデータを公開すること.すぐに使える形とは第一正規形だ.

 不満はこのくらいにして,手を動かしていこう.

実際の処理は手間隙かかる

年月日の扱いに注意

 処理に入る前に年月日の記述について確認しておく.各ページの最後に繰り返し記載されているが,

最早・最晩以外の起日については,年界を越えて前年もしくは翌年にずれ込んで発生した現象についても,当年の欄に発生月日が記述される.

 おい,ちょっと待て.単純に年と月日を結合して DATE 型のデータを作成しようとしていたのに.余計な手間かけさせやがって.

当年か,前年か,どう判別する?

 ワークシートをテーブルに変換してフィルターを覗いてみたところ,12 月に咲いている地域がある.主に八重山諸島あたりの低緯度の地域が多そうだ.とはいえ,データ処理には関係ない.サクラの特性からして,月日のデータ長が 4 桁なら前年とみなして良さそうだ.

IF LEN(#MonthDay) = 4 THEN #Year = #Year - 1 ELSE #Year END IF…(1)

 上記の仮想的なコードを組んでみる.「サクラに限れば」問題なさそうだ.しかし,秋の紅葉など他の生物の特性ではまた別のロジックが必要になることは言うまでもない.

DATE型のデータを組む

 もっとも重要な年の判別ロジックができたら,後は文字列をつないで Date 型のデータを組む.

#Date = Datevalue(#Year & #Month & #Day)…(2)

#Month = LEFT(#MonthDay, 1)…(3)

#Month = LEFT(#MonthDay, 2)…(4)

#Day = Right(#MonthDay, 2)…(5)

 日の値(#Day)は右から二桁取ってくるだけで良い.月の値(#Month)はデータ長により変わる.式 (1) に式 (2) を代入すると次の式 (6) となる.

IF LEN(#MonthDay) = 4 THEN #Date = Datevalue(#Year - 1 & #Month & #Day) ELSE #Date = Datevalue(#Year & #Month & #Day) END IF…(6)

 こんなところだろうか.式 (6) に式 (3), (4), (5) を代入すると次の式 (7) となる.#MonthDay のデータ長が 3 か 4 かで月のデータ長を変えているところにも注目してほしい.

IF LEN(#MonthDay) = 4 THEN #Date = Datevalue(#Year - 1 & LEFT(#MonthDay & 2) & Right(#MonthDay, 2)) ELSE #Date = Datevalue(#Year & #Month = LEFT(#MonthDay, 1) & Right(#MonthDay, 2)) END IF…(7)

 これが処理の中核となるコードだ.

LEN関数,LEFT関数,RIGHT関数,DATEVALUE関数,IF 関数をネストしてロジックを組み立てる
LEN関数,LEFT関数,RIGHT関数,DATEVALUE関数,IF 関数をネストしてロジックを組み立てる

実際には手動で…

 と思ったのだが,いざ VBE を起動するとコードを書く気が失せた.若い頃はワークシート丸ごと変数に放り込んで2次元配列にしてちまちま取り出してたんだけどね.誰かできる人,お願い.

 2列ずつ列を挿入しようとして選択してから右クリックしたら…

おい,複数列まとめて挿入できないじゃないか

 全くなんて仕様だ.1列ずつちまちま挿入しろってか.もちっと融通きかせてもらえないものかな.ちなみにまとめて削除もできない仕様だ.クソだな.

LEN関数,LEFT関数,RIGHT関数,DATEVALUE関数を駆使する

 ワークシート関数で日付に関連した関数はいくつかある.今回用いたのは4種類だ.月日のデータが3桁ないし4桁で記述されており,日は必ず2桁あることに注目した.右から2桁取れば残りは月のデータだけだ.まず,月を取り出そう.

=LEN(@MonthDay) - 2…(8)

 月の桁数はこれでよい.次は月そのものの値を取り出す.

=LEFT(LEN(@MonthDay) - 2, 2)…(9)

 日の値は右から2桁取り出したもの.

=RIGHT(@MonthDay, 2)…(10)

 年はちょっと判別ロジックを組み込んだ式になる.

=IF(LEN(@MonthDay)=4, @Year - 1, @Year)…(11)

 年,月,日の値をそれぞれ半角スラッシュで結んで結合する.(11), (9), (10) の順につなぐ.

=IF(LEN(@MonthDay)=4, @Year - 1, @Year)&"/"&LEFT(LEN(@MonthDay) - 2, 2)&"/"&RIGHT(@MonthDay, 2)…(12)

 これだけではまだ日付として認識されていない.式 (12) を DATEVALUE 関数で囲んで初めて DATE 型のデータになる.

=DATEVALUE(IF(LEN(@MonthDay)=4, @Year - 1, @Year)&"/"&LEFT(LEN(@MonthDay) - 2, 2)&"/"&RIGHT(@MonthDay, 2))…(13)

 こんな感じになる.@ のついた変数はテーブルで列を表している.マイナスのついたセルを参照するとエラーが発生するが,後で消すから今はこのままにしておく.

 最初は 5 桁の整数が表示されるが,慌てなくてよい.これはシリアル値といって,システム内部の数値であり,1900 年 1 月 1 日を起点として始まる年月日を表している.表示形式で日付型を指定してやればちゃんと見慣れた形式になる.

5桁の整数が表示されても慌てない.年月日はシリアル値で内部的に処理されている
5桁の整数が表示されても慌てない.年月日はシリアル値で内部的に処理されている

関数のネストは3層まで

 関数がいくつも組み合わされると,めまいがしてくる人もいるだろう.慣れないうちは無理にネストするよりも一列ずつ参照セルを挿入し,順に隣のセルを参照したほうがよい.

今回のハイライト.関数のネストはEXCELの醍醐味の一つである
今回のハイライト.関数のネストはEXCELの醍醐味の一つである

 エラーが発生した時,修復に時間がかかるためだ.

 中級者以上ならいくつかの関数を組み合わせることもできるようになっているはずだが,経験上 3 層以上のネストは後から理解するのが難しい.

 引き継ぐ必要のあるワークシートなら,セル参照により隣の列を参照するようにしたほうがロジックの流れが明快になって分かりやすい.

同じ作業をひたすら繰り返す

 地味な作業である.1953 年から 2018 年までの 65 回,同じ作業を繰り返す.こういうところこそ VBA に任せたいのだが,ワークシート関数で始めてしまったから続けるしかない.

 官僚はこういう作業,得意なんだろうな.こういう作業が苦にならない自分も官僚向きなのかも知れないなどと要らぬことを考えながら作業を続ける.

最後は「値のみ貼り付け」

 ひたすら辛い作業が終わったら,全体を選択して「コピー」「値のみ貼り付け」する.これでセル間の参照関係が解消され,自由に切り貼りの編集ができるようになる.

 これをしないと,作業列を削除した途端に参照エラーが発生してパニックを起こすことになる.忘れないようにしよう.

4列ずつ下へ切り貼り

 これも単純作業だ.先の図の第2階層を解きほぐす作業にあたる.

作業列の削除

 年月日の列さえあれば後は不要だ.地点番号,地点名,rm, 年月日を残して他の列は削除しよう.テーブルのままだと複数の行はまとめて削除できるのに,列は同じことができない.不思議だ.テーブルをいったん「範囲に変換」すると複数列の削除ができるようになる.

「範囲に変換」は「デザイン」タブにある
「範囲に変換」は「デザイン」タブにある
作業列の削除はテーブルをいったん「範囲に変換」してから
作業列の削除はテーブルをいったん「範囲に変換」してから

テーブル,再び

 不要な列を削除したら,全領域をテーブルに変換する.

フィルターで不要な行を削除

 フィルターをかけると不要な行がいっぱい出てくる.確認しつつ削除する.手動の作業のため地点名が抜けているところがあり,コピペで対応する.

平年値,最早値,最早年,最晩値,最晩年は別テーブルへ

 ところで,テーブルの最後に余計なデータがある.これは集計関数による別のデータとみなすべきで,同じテーブルに格納すべきではない.ワークシートごと別のテーブルに分けるべきだ.

 こういう余計な作業を強いるあたり,親切というべきか融通が効かないと言うべきか.

.txtファイルで保存

 004ワークシートを .txt ファイルに保存する.これでデータベースにインポートできるようになった.

SQL Serverへのインポート

ウィザードを使ってファイルをインポートする.5843件のデータだ
ウィザードを使ってファイルをインポートする.5843件のデータだ

まとめ

気象庁の生物季節観測値には心底がっかりした

 思いついてから丸三日かかって気象庁の PDF ファイルを第一正規形に変換した.比較的単純な作業の繰り返しだったが,最初から第一正規形で置いてあればこんな手間隙かけずに済んだのに.本当に残念だ.

官僚には猛省を促したい

 本来なら即座にデータベースにインポートできる第一正規形で公開するのが筋だ.気象庁だけではない.霞ヶ関にはデータベースのことが分かっている人間がいないのか.ITだAIだ言う前に,あるだけで利用できないデータを何とかしてくれ.

“気象庁のサクラ開花日のテキストファイル” への2件の返信

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください