2014年7月22日火曜日

エクセルの日付(シリアル値)を、Rで使えるように変換する

例えば、セルの1つに「2014年7月22日」と入力してあったとしましょう。



これをXLConnectパッケージを使ってRで読み込むと、

> library(XLConnect)
> wb <- loadWorkbook("input.xlsx")
> ws <- readWorksheet(wb, sheet=1, header=F)
> ws
   Col1
1 41842

のように、「2014年7月22日」と入力してあったセルの値が、「41842」となっています。

これはシリアル値といって、1900年1月1日を「1」、1月2日を「2」、・・・として日付を数値化したもので、エクセルは内部的にはこのように日付データを保持しています。というのを知っている人は多いと思います。

じゃあ、この値を日付としてRから使いたいときにどうやるのか? というのが今回のエントリの目的です。

Rには日付のシリアル表現のための関数があって、整数値と起源日付を指定することによって、シリアル値を日付(Date)型に変換することができます。

ということは、↓これでいけるはずだが・・・

> as.Date(41842, origin="1900-01-01") # 2014年7月22日のつもり
[1] "2014-07-24"

あれ? 2日ほどずれている。

このずれの原因の1つ目は以下のコードを実行することで、すぐに理解できます。

> as.Date(0, origin="1900-01-01")
[1] "1900-01-01"

> as.Date(1, origin="1900-01-01")
[1] "1900-01-02"

> as.Date(2, origin="1900-01-01")
[1] "1900-01-03"

エクセルでは1900年1月1日を「1」としているのに対し、Rのas.Date関数はoriginオプションで指定された日付(つまり1900年1月1日)を「0」としているわけですね。0オリジン vs 1オリジン のゴタゴタがこんなところにまで・・・

そして、ずれの原因の2つ目は、エクセルでシリアル値を実際に表示してみると判明します。

エクセル上でシリアル値を確認したい場合は、日付が入っているセルの書式設定で、表示形式タブを選択、ユーザー定義で「G/標準」を指定すればOKです。



絶対的な真理として、1900年はうるう年ではありません。つまり、1900年2月29日は存在せず、2月28日が59なら、3月1日を60にするべきなのです。なのに、そうなっていないせいで、1900年3月1日以降(あなたが扱うであろうほとんどの日付)に関しては、このずれが発生してしまうことになります。

このバグとも思えるような変な仕様は、(当時有力だった)「Lotus1-2-3」との互換性を維持するための意図的なものであったとのこと。

なんて、いきさつのことは知らなくても、やり方だけ覚えておけばOK。

 【A】origin="1900-01-01"と指定するなら、シリアル値から2を引く または

というのでもいいけど、↓こっちの方がシンプルかも

 【B】origin="1899-12-30"と指定する

【B】の方は、マニュアルにも書いてあって(?as.Dateと打てば見られます)、

## So for dates (post-1901) from Windows Excel
as.Date(35981, origin = "1899-12-30") # 1998-07-05

というサンプルが載っています。

マッキントッシュは起源日付が違うので、マック版エクセルでは、以下のようにすればいいらしいです。

## and Mac Excel
as.Date(34519, origin = "1904-01-01") # 1998-07-05


 ウィンドウズ版: origin = "1899-12-30"
 マック版   : origin = "1904-01-01"

というオプション指定だけを覚えてしまえば十分ですね。




0 件のコメント:

コメントを投稿