らくがきちょう

文字数制限の無いTwitter的な

(解析メモ)時刻のデータをExcelやMatlabで扱う

時刻データは何かとめんどくさい。

Excelに時刻を、たとえば19時40分を19:40と入力すると、まずはその通り表示してくれる。ここまではいい。

f:id:MshrOkn:20201013193923p:plain



ところが、これをMatlabで読み込んでやると、次のように様子がおかしくなる。

f:id:MshrOkn:20201013193603p:plain

0.8194、とは…???

以下、こいつと戦って分かったことのメモ。乱筆乱文にも程がありますがご容赦ください。

 

時刻シリアル値

この謎の小数は、Excelでは「時刻シリアル値」と呼ばれている。Excel上で、このセルの書式を「標準」などに変更してやると19:40と表示されていたのがこの数値になる。どうも時刻らしき入力が来ると勝手に変換される模様。

f:id:MshrOkn:20201013193857p:plain

 

時刻シリアル値について簡単に知りたい場合は、適当なセルに「=TIME」または「=TIMEVALUE」という関数を打ち込んでみると説明がポップアップしてくる。

曰く、

f:id:MshrOkn:20201013194349p:plain

指定した時刻を表すシリアル値(0:00:00(午前12:00:00)から23:59:59(午後11:59:59)までを表す0から0.9999999の範囲の小数値)を」返します。

 つまり24時間=86400秒を[0 1)の区間の数値に対応させているらしい。

なので、たとえば適当なセルに「0.25」と打ち込み、そのセルの書式を「時刻」にしてやれば「6:00:00」と表示されるようになる。

f:id:MshrOkn:20201013200201p:plain

当然、「0.75」なら「18:00:00」となる。時刻だけ入力した場合、Excelはこういう風に認識するらしい。

 

1を超える値を時刻シリアルに入力すると…?

悪戦苦闘の末に気づいたのだけど、「1.5」と入力して書式を「時刻」にするという意地悪をしてみるとこうなった。

f:id:MshrOkn:20201013200056p:plain

どうやら「1.5」はExcel的には「1900/1/1 12:00:00」らしい。西暦と日付が表れた。

ということは、任意の数を入力すれば整数部分で日付(1900/1/1を1とする)、小数部分で時刻を表せることになる。

実際、365.3333333と入力したら1900/12/30 8:00:00になった。ちゃんと閏年も考えてくれてるらしい(そりゃそうか)。ただし、残念ながら負の数は受け付けてくれない模様(########って表示された)(かつて絵文字で#でいらだちが表されていたのをふと思い出す)(Excel先生お怒り…?)

 

Matlabにおける時刻シリアル値

時刻シリアル値的な物はMatlabにもあり、DateNumberとよばれている。0:00:00~23:59:59を[0 1)に対応させるのはExcelと同じ。

ただし、整数部分0に対応する日付はMatlabの場合、-0001/12/31らしい。

このことは、Matlabのコマンドウィンドウに

datetime(0, 'ConvertFrom', 'datenum')

と入力して実行すると確かめられる。

datetime(3.25, 'ConvertFrom', 'datenum')

なら 0000/1/03 06:00:00だ。

なおさすがのMatlab先生は負の数にも対応しているようで、

datetime(-5+0.25, 'ConvertFrom', 'datenum')

と入力したところ -0001/12/26 06:00:00 と返してくれた。

なおdatetime関数は「日付と時刻に対応するスカラー値(datetime型)(の配列)」を返す関数で、色々な型(文字列型やdouble, single型のシリアル値など)で入力されている日付時刻をdatetime型に変換するのに使う。

逆に日付時刻をシリアル値に変換したければdatenum関数を用いる。詳しくはドキュメンテーションを見てください。

時点を表す配列 - MATLAB - MathWorks 日本

日付と時刻をシリアル日付値に変換 - MATLAB datenum - MathWorks 日本

 

Excelで入力した時刻データをMatlabで処理する

そんなわけで、ExcelMatlabで時刻データを処理したいときは、上記のようなシリアル値の挙動を念頭に置いておくとよい。

今回いじっていたデータで得た教訓としては、

 

Excelも日付計算はできる。ただしシリアル値のことを知らないと、一瞬何が起こったのか分からない。

f:id:MshrOkn:20201013204152p:plain

Excelは参照したセルが日付時刻だと言うことは考慮してくれるほどには気が利かないので、計算結果がシリアル値で表示されてしまう。

落ち着いて表示形式を「時刻」に変換すれば、正しく引き算が出来ていることがわかる。

 

Excelに打ち込むデータとしては年、月、日、時刻ごとに列を分けるとMatlabでいじるときはかどる(たぶん)

たとえばこういうデータ↓をインポートしようとすると、

f:id:MshrOkn:20201013205149p:plain

Matlabのインポートツールではこうなる。

f:id:MshrOkn:20201013205226p:plain

こういう形式にしておけば、たとえば次のような入力で日付時刻の計算が比較的簡単にできる(R2019bの場合。古いバージョンだともう少し工夫がいる場合があるかも)(datetime型同士では計算できないが、datetime + 数値なら時刻シリアル値と思って計算してくれるということ)。

f:id:MshrOkn:20201013205830p:plain

時刻だけ、もしくは1つのセルに年月日時刻をまとめて打ち込む形のを読み込んだ場合もなんとかしようと思えば出来るが、結構めんどくさかった。

特に今回自分が扱うデータは日付をまたいだ時刻データが含まれていたので、めんどくさがって時刻だけExcelに入力したために地獄を見た。

 

悪戦苦闘の果ての暫定的結論はこんな感じ。もっといい方法とか実践例とかご存じの方は教えてくださるとうれしいです。